Esta questão é um mistério para mim e ficarei extremamente feliz em encontrar a solução. Fornecerei os detalhes do meu ambiente que considero relevantes, mas, se precisar de mais alguma coisa, por favor, comente e acrescentarei.
A infraestrutura:
host - digital ocean droplet
os - Ubuntu 17.04
proxy reverso - nginx 1.12.0 (o problema aconteceu também no nginx 1.10.0)
servidor de aplicativos - node-js 7.10.0 (também aconteceu em 7.9.0)
clients - Android (acontece em várias versões, incluindo 5.0, 6.0.1, 7.1.1, provavelmente não relacionadas) usando o OkHttp 3.8.0
Assim, o nginx encaminha o tráfego para o nodejs e o nodejs processa as solicitações dos clientes do Android.
A questão:
Para alguns clientes, de vez em quando, para uma consulta específica, o json recebido pelo nodejs é malformado. especificamente, vários bytes são escritos no início do json do corpo,
Aqui está um exemplo:
2017-05-24 15:42:14.899 (+0300) - error: Error summary:
name: SyntaxError
status: 400
request: POST /api/v1/user_details
body:
J ount_id":"217627","user":{"email": "[email protected]" ....<rest of json is ok>
observe o início do corpo - parece que vários bytes malformados sobrescrevem o início do json original. às vezes não há bytes estranhos, apenas o json original é cortado, e. ser ": {" email ":" [email protected] ".... Ele fica mais estranho - acontece apenas de vez em quando (talvez uma em 100 chamadas), para apenas alguns clientes, em um endpoint específico (embora eu não tenha muitos endpoints, e este é usado muito) e até mesmo nesses clientes - apenas uma vez em muitos pedidos. Não é específico para um determinado dispositivo (aconteceu na LG, Samsung, OnePlus, pelo menos), e dos logs que recebo em clientes, usando um interceptador OkHttp para ver quais dados são enviados, parece correto. Eu até tentei enviar a mesma solicitação que falhou nos registros de um cliente, no meu dispositivo, e foi bem-sucedida. Tentei reconstruir esse bug sem sucesso - bombardeei o servidor com solicitações, de vários dispositivos, para ver se era uma questão de grandes números, mas nenhum deles produziu esse problema. Além disso, na investigação, tentei ver exatamente onde os dados ficam malformados - notei que, antes de todos os middlewares, o nodejs recebe o corpo malformado. Eu adicionei o registro de corpos no nginx, e notei que o próprio nginx recebe os dados malformados.
Este é um dos problemas mais estranhos que eu já encontrei, e eu realmente espero que alguém possa me dizer exatamente o que está acontecendo.
Configuração Nginx:
/ etc / nginx / sites-enabled / default
# HTTP - redirect all requests to HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name my-service.com, app.my-service.com, www.my-service.com;
# letsencrypt auto-renew
location ~ /.well-known {
root /var/www/html;
}
location / {
return 301 https://$server_name$request_uri;
}
#return 301 https://$server_name$request_uri;
}
#log_format postdata '[$time_local] "$request" $status '
# '$request_body';
server {
# SSL configuration
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/ssl-my-service.com.conf;
include snippets/ssl-params.conf;
# Pass requests for / to localhost:3000:
location / {
# used to log traffic's post body data when uncommented:
# access_log /var/log/nginx/postdata.log postdata;
# echo_read_request_body;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass https://localhost:3000/;
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;
}
}
snippets / ssl-params.conf
ssl_certificate /etc/letsencrypt/live/my-service.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-service.com/privkey.pem;
snippets / ssl-my-service.com.conf
server_tokens off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/my-service.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=86400;
resolver_timeout 10s;
UPDATE 1:
Aqui estão os cabeçalhos de solicitação enviados pelo cliente Android:
Tipo de Conteúdo: application / json; charset = UTF-8, Content-Length: 5689, Autorização: Portador, User-Agent: MyServiceApp / 1.0.0 (Android 7.1.2)
Tags ssl nginx ubuntu node.js lets-encrypt