2015-04-21 3 views
4

У меня есть много запросов HTTP POST, отправляемых на сервер nginx, которые затем уравновешивают нагрузку на набор обратных прокси-серверов node.js/express.js. Чтобы сэкономить некоторое сетевое потребление, полезная нагрузка отправляется с использованием GZIP и заголовка Content-Encoding: gzip.Nginx gunzip POST-запросы на backend

Я пытаюсь добиться чего-то вроде этого:

[Client] [Nginx Reverse Proxy] [BackEnd] | [gziped payload] | [raw payload] |
|--------------------> | ----------------------------->| | | |
| [Raw Response] | [Raw response] | | <------------------ | <-----------------------------| | | |

По соображениям эффективности я хочу запустить Gunzip на Nginx пока я не был в состоянии сделать это. Вот файл HTTP nginx.conf:

http { 
    include  mime.types; 
    default_type application/octet-stream; 
    sendfile  on; 
    keepalive_timeout 65; 

    server { 
     listen  80; 
     server_name localhost; 
     gunzip on; 
     location/{ 
      proxy_pass http://localhost:8080; 
      proxy_http_version 1.1; 
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection 'upgrade'; 
      proxy_set_header Host $host; 
      proxy_cache_bypass $http_upgrade; 
      } 
    } 
} 

Вот пример запроса:

echo "{"id": 0,"mypayload":"This is an example"}" | gzip -c - | curl -v -i -X POST -H 'Content-Encoding: gzip' --data-binary '@-' http://localhost/test 

Я хотел Nginx, чтобы распаковать содержимое полезной нагрузки и доставить сырой контент на внутренний сервер, но содержимое до сих пор поставляется сжатым.

Я видел много людей, которые делают наоборот (ответы Nginx gziping и даже ответные ответы на запросы клиентов, у которых нет заголовка Accept-Encoding: gzip), но не смогли найти его с помощью gunziping полезных нагрузок на бэкэнд ,

Любые подсказки?

+0

Вы нашли ответ на этот вопрос еще? Какой процесс вы в конечном итоге прошли? – bibstha

+0

@bibstha пока я делаю gzip-декодирование на бэкэнде. Если я не могу найти альтернативу с помощью Nginx, я бы разработал простой обратный прокси-сервер с обратным прокси-сервером, чтобы сделать это после Nginx или код модуля LUA для обработки этих случаев. – Tallis

ответ

-1

Я знаю, что это старый вопрос, но я хотел сделать то же самое для клиента IOS, который отправляет запросы на сжатие, и после проверки вашего вопроса я столкнулся с решением lua, описанным here, и подумал, что опубликую его здесь для будущего Справка.

Модуль Lua выглядит следующим образом:

-- Debian packages nginx-extras, lua-zlib required 

ngx.ctx.max_chunk_size = tonumber(ngx.var.max_chunk_size) 
ngx.ctx.max_body_size = tonumber(ngx.var.max_body_size) 

function create_error_response (code, description) 
    local message = string.format('{"status":400,"statusReason":"Bad Request","code":%d,"exception":"","description":"%s","message":"HTTP 400 Bad Request"}', code, description) 
    ngx.status = ngx.HTTP_BAD_REQUEST 
    ngx.header.content_type = "application/json" 
    ngx.say(message) 
    ngx.exit(ngx.HTTP_OK) 
end 


function inflate_chunk (stream, chunk) 
    return stream(chunk) 
end 


function inflate_body (data) 
    local stream = require("zlib").inflate() 
    local buffer = "" 
    local chunk = "" 

    for index = 0, data:len(), ngx.ctx.max_chunk_size do 
     chunk = string.sub(data, index, index + ngx.ctx.max_chunk_size - 1) 
     local status, output, eof, bytes_in, bytes_out = pcall(stream, chunk) 

     if not status then 
      -- corrupted chunk 
      ngx.log(ngx.ERR, output) 
      create_error_response(4001, "Corrupted GZIP body") 
     end 

     if bytes_in == 0 and bytes_out == 0 then 
      -- body is not gzip compressed 
      create_error_response(4002, "Invalid GZIP body") 
     end 

     buffer = buffer .. output 

     if bytes_out > ngx.ctx.max_body_size then 
      -- uncompressed body too large 
      create_error_response(4003, "Uncompressed body too large") 
     end 
    end 

    return buffer 
end 


local content_encoding = ngx.req.get_headers()["Content-Encoding"] 
if content_encoding == "gzip" then 
    ngx.req.read_body() 
    local data = ngx.req.get_body_data() 

    if data ~= '' then 
     local new_data = inflate_body(data) 

     ngx.req.clear_header("Content-Encoding") 
     ngx.req.clear_header("Content-Length") 
     ngx.req.set_body_data(new_data) 
    end 
end 

, а затем вы можете использовать его как:

location/{ 
     proxy_pass http://127.0.0.1:8080; 
     proxy_pass_request_headers on; 
     proxy_redirect off; 
     proxy_set_header X-Real-IP $remote_addr; 

     client_max_body_size 512k; # Max request body size of 512 KB 
     client_body_buffer_size 512k; 

     set $max_chunk_size = 10240; # Chunks of 10 KB 
     set $max_body_size = 524288; # Max inflated body size of 512 KB 

     rewrite_by_lua_file inflate_body.lua; 
    } 
+0

Какие версии lua и lua-zlib вы используете для этого модуля? спасибо! – imapollo

+1

Еще один проголосовавший без объяснений; Я ненавижу, что это не помогает поведению. В любом случае, я предполагаю, что одна проблема связана с 'ngx.req.get_headers() [" Content-Encoding "]', которая вместо этого должна использовать 'ngx.resp.'. – adrhc