Reputation: 1
I am deploying a container to an Azure Web App for Containers instance. The container bundles an Nginx server and RClone. The Nginx reverse proxy validates the request using an auth_request
directive and then proxy_pass
to the RClone upstream server on localhost.
Copied to /etc/nginx/conf.d/timeout.conf
:
client_header_timeout 1800;
client_body_timeout 1800;
proxy_connect_timeout 1800;
proxy_send_timeout 1800;
proxy_read_timeout 1800;
send_timeout 1800;
Copied to /etc/nginx/nginx.conf
.
pid /var/run/nginx/nginx.pid;
load_module modules/ngx_http_js_module.so;
worker_processes auto;
events {
worker_connections 1024;
}
http {
resolver 127.0.0.11 ipv6=off;
resolver_timeout 10s;
default_type application/json;
keepalive_timeout 65;
client_max_body_size 0;
upstream rclone {
server localhost:5572;
}
upstream validator {
server localhost:8079;
}
js_path "/etc/nginx/njs/";
js_import main from index.js;
server {
listen 8000;
listen [::]:8000;
server_name localhost;
sendfile on;
client_header_buffer_size 32k;
location / {
access_log off;
return 200;
}
location /healthcheck {
access_log off;
return 200;
}
location ~* /operations/uploadfile {
limit_except HEAD POST { deny all; }
auth_request /_validate;
proxy_set_header Content-Length $content_length;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_request_buffering off;
proxy_intercept_errors off;
proxy_pass http://rclone;
}
location = /_validate {
internal;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_pass_request_body off;
proxy_intercept_errors off;
proxy_pass http://validator/validate;
}
error_page 405 = @405;
location @405 { return 405 '{"status":405,"code":"MethodNotAllowed","message":"Method Not Allowed"}\n'; }
error_page 500 = @500;
location @500 { return 500 '{"status":500,"code":"InternalServerError","message":"Internal Server Error"}\n'; }
}
server {
listen 8079;
listen [::]:8079;
server_name localhost;
client_header_buffer_size 32k;
location /validate {
js_content main.authorize;
js_fetch_timeout 10;
js_fetch_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
}
}
}
It was my understanding that idle timeouts don't apply to active data uploads with data in transit. Depending on network latency/bandwidth, large uploads that take longer than ~5 minutes are being canceled.
#!/bin/bash
curl -v -X POST 'https://<redacted>.azurewebsites.net/operations/uploadfile?<rclone_query_params>' \
-H @token.txt \
-F file=@"../samples/test-500MB.file"
const fs = require('fs');
const axios = require('axios');
const domain = 'https://<redacted>.azurewebsites.net';
const file = '../samples/test-500MB.file';
const fileStream = fs.createReadStream(file);
const token = fs.readFileSync('./token.txt', 'utf8').split(':')[1].trim();
console.log(`Uploading file: ${file}`);
console.log(`Token: ${token}`);
axios({
method: 'post',
url: `${domain}/operations/uploadfile?<rclone_query_params>`,
headers: {
'Content-Type': 'application/octet-stream',
'Content-Length': fs.statSync(file).size,
Expect: '100-continue',
Connection: 'keep-alive',
'Transfer-Encoding': 'chunked',
'User-Agent': 'axios/0.21.4',
Authorization: `${token}`
},
data: fileStream,
maxContentLength: Infinity,
maxBodyLength: Infinity,
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`Upload progress: ${percentCompleted}%`);
},
validateStatus: (status) => {
return (status >= 200 && status < 300) || status === 308;
},
maxRedirects: 0
})
.then((response) => {
console.log(`Upload completed: ${response.status} ${response.statusText}`);
})
.catch((error) => {
console.error(`Upload failed: ${error.message}`);
});
It doesn't appear to be an issue between Nginx and RClone. The request authorizes successfully and starts to upload in parts via multipart upload. After ~300 seconds the client connection is closed by Azure with the following logs.
2023/05/13 13:01:34 [info] 18#18: *15 client prematurely closed connection while sending request to upstream, client: <redacted>, server: localhost, request: "POST /uploadfile?<rclone_query_param> HTTP/1.1", upstream: "http://127.0.0.1:5572/operations/uploadfile?<rclone_query_param>", host: "<redacted>.azurewebsites.net"
2023/05/13 13:01:34 ERROR : rc: "operations/uploadfile": error: multipart upload failed to upload part: context canceled
Failed to forward request to http://<redacted>. Encountered a System.Threading.Tasks.TaskCanceledException exception after 299998.262ms with message: The request was canceled due to the configured HttpClient.Timeout of 300 seconds elapsing.. Check application logs to verify the application is properly handling HTTP traffic.
Any insight is appreciated.
Upvotes: 0
Views: 666