Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ngx.fetch Content-Length header is not sent #693

Closed
Masterwow3 opened this issue Jan 31, 2024 · 8 comments
Closed

ngx.fetch Content-Length header is not sent #693

Masterwow3 opened this issue Jan 31, 2024 · 8 comments

Comments

@Masterwow3
Copy link

With the current Nginx version nginx/1.24.0 there are no headers on the server that contain a minus sign in the key.

Example, works. The header x arrives at the server:
await ngx.fetch("https://yxy/asd", { verify: false, headers: { 'x': "a" } });

Example, header x-ms does not arrive at the server:
await ngx.fetch("https://yxy/asd", { verify: false, headers: { 'x-ms': "a" } });

@xeioex
Copy link
Contributor

xeioex commented Feb 1, 2024

Hi @Masterwow3,

I cannot reproduce the problem so far, I am using the following config and js code

error_log /dev/stdout info;
daemon off;
master_process off;

events { }

http {
    js_import main from fetch.js;

    resolver 1.1.1.1;

    server {
        listen       8000;

        location / {
            js_content main.fetch;
        }
    }

    server {
        listen       8001;

        location / {
            js_content main.reply;
        }
    }
}

async function fetch(r) {
    let reply = await ngx.fetch("http://127.0.0.1:8001/",
                                { headers: { 'x-ms': "a", 'foo': 'xxx' } })

    let body = await reply.text();

    r.return(200, body);
}

function reply(r) {
    let body = [njs.version, '\n'];
    r.rawHeadersIn.forEach((header) => {
        body.push(`${header[0]}: ${header[1]}\n`);
    });

    r.return(200, body.join(''));
}

export default { fetch, reply };

To run the nginx:
nginx -c fetch.conf

curl http://127.1:8000/                            
0.7.10                                                                                                                                   
Host: 127.0.0.1                                                     
Connection: close                                                   
x-ms: a                                                                                                                                  
foo: xxx

I tried njs versions from 0.7.10 to 0.7.12 and the latest one 0.8.2. Which njs version are you using?

@Masterwow3
Copy link
Author

Masterwow3 commented Feb 1, 2024

Hi @xeioex,
thanks for your reply, you are right, the mirror I was using swallowed the headers.

But there is still a problem. The header Content-Length cannot be set. This does not reach the server.

Log output: [info] 29#29: *3 js: [["Host","10.3.2.52"],["Connection","close"],["x-ms","123"]]
nginx/1.24.0

async function send(r) {
  await ngx.fetch("http://10.3.2.52:8082/", {
    headers: {
      "Content-Length": "0",
      "x-ms": "123"
    }
  });
  r.return(200);
}

async function log(r) {
  r.log(JSON.stringify(r.rawHeadersIn));
  r.return(200);
}


export default { send, log }
server {
  listen 8081;
  js_import njs/test.js;

  location / {
    js_content test.send;
  }
}

server {
  listen 8082;
  js_import njs/test.js;

  location / {
    js_content test.log;
  }
}

@Masterwow3 Masterwow3 changed the title missing ngx.fetch headers with minus ngx.fetch Content-Length header is not sent Feb 1, 2024
@xeioex
Copy link
Contributor

xeioex commented Feb 1, 2024

Hi @Masterwow3,

"Content-Length" and a handful of other headers are treated in a special way by nginx. For example, with "Content-Length", the value is put to r->headers_in.content_length as a number and not as a header.
Whereas both r.rawHeadersIn and r.headersIn look for ordinary headers.
In njs you can get "Content-length" by r.requestBuffer.length for the text input.

@Masterwow3
Copy link
Author

Masterwow3 commented Feb 1, 2024

Hi @xeioex,

curl -v -H "Content-Length: 0" "http://10.3.2.52:8082/"
Arrives at nginx: [info] 29#29: *2 js: [["Host","10.3.2.52:8082"],["User-Agent","curl/7.87.0"],["Accept","*/*"],["Content-Length","0"]]
It does not arrive per NJS.

await ngx.fetch("http://10.3.2.52:8082/", {
    headers: {
      "Content-Length": "0",
      "x-ms": "123"
    }
  });

Does that mean I can't send this header via njs?

@xeioex
Copy link
Contributor

xeioex commented Feb 1, 2024

Hi @Masterwow3,

There are no special treatment of Content-Length in njs Fetch for headers object.
With this code https://gist.github.com/xeioex/f3ceec948833c254dfb51bee4b7e48eb
I get the following output:

curl http://127.1:8000/
0.8.3
Host: 127.0.0.1
x-ms: a
foo: xxx
Content-Length: 0
Connection: close

Can you confirm the njs version? Just output njs.version in JS code.

@Masterwow3
Copy link
Author

Hi @xeioex,

[info] 28#28: *1 js: NJS version: 0.7.12

Okay too bad, is it planned to support the header Content-Length in NJS?
I use the Microsoft Blob API which requires this header.

@xeioex
Copy link
Contributor

xeioex commented Feb 1, 2024

Hi @Masterwow3,

There WAS a special treatment for Content-Length and other headers in accordance with Fetch API (between 0.7.10 and 0.7.12). But this was reverted back since 0.8.0. The latest released version is 0.8.2.

Feel free to upgrade to nginx 1.25.3 and njs 0.8.2.

@Masterwow3
Copy link
Author

nginx/1.25.3
NJS version: 0.8.2
28#28: *3 js: [["Host","10.3.2.52"],["Content-Length","0"],["x-ms","123"],["Connection","close"]]

Thank you, it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants