Disable keep_alive based on specific useragent

Due to a bug in iOS 8, I want to disable http keep-alive for all iOS 8
useragents for now.

https://github.com/AFNetworking/AFNetworking/issues/2314

I can’t see a way to do this in nginx at the moment.

The docs for keep_alive disable only talk about msie6 and safari.

http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_disable

And indeed, checking the code shows that it’s a bitfield with only a few
fixed possible values.

All our requests are proxied to a backend, and I obviously could easily
detect the user-agent on the backend, but I can’t see any way to
indicate back to nginx that it should drop the connection to the client
after returning the response (e.g. there’s no x-accel-disable-keepalive
or something like that).

I had a quick look through the code, and can’t see anything obvious. No
configuration options, no upstream response headers, nothing even in the
nginx lua integration that could do this.

Am I missing something? It’s a bit annoying that keepalive_disable can’t
take an arbitrary regexp if people really want…


Rob M.
[email protected]

Hello,

On Mon, Nov 17, 2014 at 7:16 AM, mex [email protected] wrote:

​I would do even better by avoiding using 'if’​
​ at all:

map $http_user_agent $keepalive_timeout {
default 75s; # Put here the wanted default value (taken from
keepalive_timeout
http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
docs)
regex 0;
for 0;
blacklisted 0;
user agents 0;
}​

keepalive_timeout $keepalive_timeout; # At http, server or location
level,
as docs state

*B. R.*​

Hi

Thanks for your responses. Unfortunately, they don’t seem to work.

and then use the evil IF:

if ($ios_ua) { keepalive_timout 0; }

This doesn’t appear to work.

if ($http_user_agent ~ “^iOS/8.”) { keepalive_timeout 0; }

nginx: [emerg] “keepalive_timeout” directive is not allowed here
in nginx-http.conf:753 nginx: configuration file nginx-http.conf
test failed

If I do:

if ($http_user_agent ~ “^iOS/8.”) { keepalive_timeout 0; # }

e.g. comment out the “if” block part, it works fine, but obviously
disabled keepalive for all requests. So it appears you can’t set
keepalive_timeout in an “if” block.

I would do even better by avoiding using ‘if’ at all:

map $http_user_agent $keepalive_timeout { default 75s; # Put here the
wanted default value (taken from keepalive_timeout[1] docs) regex 0;
for 0; blacklisted 0; user agents 0 }

keepalive_timeout $keepalive_timeout; # At http, server or location
level, as docs state

This doesn’t seem to work either:

map $http_user_agent $katimeout { default 300s; }

keepalive_timeout $katimeout;

nginx: [emerg] “keepalive_timeout” directive invalid value in
nginx-http.conf:53 nginx: configuration file nginx-http.conf test failed

Looks like the value can’t be a variable?

Rob

Links:

http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout

Hi Robert,

you could probably work around this issues with map / if:

map $http_user_agent $ios8_ua {
default 0;
“YOUR_REGEX_HERE” 1;
}

and then use the evil IF:

if ($ios_ua) {
keepalive_timout 0;
}

http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
http://nginx.org/en/docs/http/ngx_http_map_module.html

cheers,

mex

Posted at Nginx Forum:

Try to remove the last ‘s’
This should work.

map $http_user_agent $katimeout {
default 300;
}

nope, this seems to be a longer-known problem:

i (at least) did not got it working, either with “default 300;”
or with

set katimeout 300;

Posted at Nginx Forum:

On Tuesday 18 November 2014 07:11:01 mex wrote:

nope, this seems to be a longer-known problem:

please allow keepalive_timeout and keepalive_requests to accept variables

i (at least) did not got it working, either with “default 300;”
or with

set katimeout 300;

If a directive supports variables, it’s always explicitly mentioned
in the documentation.

wbr, Valentin V. Bartenev