snapCloud icon indicating copy to clipboard operation
snapCloud copied to clipboard

Internal error on handling HTTP-request with duplicated header keys: Accept, Content-Type and Origin

Open Toliak opened this issue 10 months ago • 1 comments

Is there an existing issue for this?

No. I have searched the existing issues. Used queries:

  • attempt to call method 'match', attempt to call method 'find', attempt to call method 'gsub'
  • duplicate, header

Similar issue: https://github.com/leafo/lapis/issues/794

Version

I used snapCloud master branch, commit b3d2a4c

luarocks list
# luarocks list

ansicolors
   1.0.2-3 (installed) - /usr/local/lib/luarocks/rocks

argparse
   0.7.1-1 (installed) - /usr/local/lib/luarocks/rocks

date
   2.2.1-1 (installed) - /usr/local/lib/luarocks/rocks

etlua
   1.3.0-1 (installed) - /usr/local/lib/luarocks/rocks

inspect
   3.1.3-0 (installed) - /usr/local/lib/luarocks/rocks

lapis
   1.16.0-1 (installed) - /usr/local/lib/luarocks/rocks

loadkit
   1.1.0-1 (installed) - /usr/local/lib/luarocks/rocks

lpeg
   1.1.0-2 (installed) - /usr/local/lib/luarocks/rocks

lua-cjson
   2.1.0.10-1 (installed) - /usr/local/lib/luarocks/rocks

lua-resty-http
   0.17.2-0 (installed) - /usr/local/lib/luarocks/rocks

lua-resty-mail
   1.1.0-1 (installed) - /usr/local/lib/luarocks/rocks

luabitop
   1.0.2-1 (installed) - /usr/local/lib/luarocks/rocks

luafilesystem
   1.8.0-1 (installed) - /usr/local/lib/luarocks/rocks

luaossl
   20220711-0 (installed) - /usr/local/lib/luarocks/rocks

luasec
   1.3.2-1 (installed) - /usr/local/lib/luarocks/rocks

luasocket
   3.1.0-1 (installed) - /usr/local/lib/luarocks/rocks

lub
   1.1.0-1 (installed) - /usr/local/lib/luarocks/rocks

pgmoon
   1.16.0-1 (installed) - /usr/local/lib/luarocks/rocks

snapcloud
   dev-0 (installed) - /usr/local/lib/luarocks/rocks

xml
   1.1.3-1 (installed) - /usr/local/lib/luarocks/rocks

Error

Duplicated HTTP headers Accept, Content-Type and Origin in the request lead to 500 (Internal Error).

It happens due to unusual behavior of the ngx.req.get_headers function. Consider simple example:

local my_header = ngx.req.get_headers()["X-MyHeader"]

The variable my_header may be:

  • nil, if there is no header named X-MyHeader
  • string (if only one header provided)
  • or (!) table (if multiple headers provided).

The snapCloud code assumes the value only as a nil or a string and, therefore, if there are multiply headers -- the code crashes and produces 500 error code. The example of dealing with the table type case: https://github.com/Kong/kong/pull/14331/files#diff-71ca7cc8d190667cccff84bdd38a242104adcaa8a3a844874aa518484fdf291fR260

Duplicated Accept header

Logs from the server
, client: 127.0.0.1, server: 9dd6683d475e, request: "GET / HTTP/1.1", host: "127.0.0.1:8080"
2025/03/09 16:28:40 [error] 22283#22283: *198 lua entry thread aborted: runtime error: ./responses.lua:77: attempt to call method 'match' (a nil value)
stack traceback:
coroutine 0:
	./responses.lua: in function 'handle_error'
	/usr/local/share/lua/5.1/lapis/application.lua:196: in function 'render_error_request'
	/usr/local/share/lua/5.1/lapis/application.lua:228: in function 'dispatch'
	/usr/local/share/lua/5.1/lapis/nginx.lua:231: in function 'serve'
	content_by_lua(nginx.conf.d/locations.conf:32):2: in main chunk, client: 127.0.0.1, server: 9dd6683d475e, request: "GET / HTTP/1.1", host: "127.0.0.1:8080"
2025/03/09 16:28:40 [notice] 22283#22283: *200 "^/(.*)\.html$" does not match "/", client: 127.0.0.1, server: 9dd6683d475e, request: "GET / HTTP/1.1", host: "127.0.0.1:8080"
2025/03/09 16:28:40 [error] 22283#22283: *200 connect() failed (111: Connection refused), client: 127.0.0.1, server: 9dd6683d475e, request: "GET / HTTP/1.1", host: "127.0.0.1:8080"
2025/03/09 16:28:40 [notice] 22283#22283: *200 [lua] global.lua:39: debug_print(): 

Related sources:

https://github.com/snap-cloud/snapCloud/blob/b3d2a4c048ab8b0df1f936c47d942c0790da8034/responses.lua#L77

Duplicated Content-Type header

Logs from server
./app.lua:184: attempt to call method 'find' (a nil value)
"\nstack traceback:
    \n\t./app.lua:184: in function 'filter'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:22: in function 'run_before_filter'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:176: in function 'resolve'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:216: in function </usr/local/share/lua/5.1/lapis/application.lua:214>
    \n\t[C]: in function 'xpcall'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:214: in function 'dispatch'
    \n\t/usr/local/share/lua/5.1/lapis/nginx.lua:231: in function 'serve'
    \n\tcontent_by_lua(nginx.conf.d/locations.conf:32):2: in main chunk"

Related sources:

https://github.com/snap-cloud/snapCloud/blob/b3d2a4c048ab8b0df1f936c47d942c0790da8034/app.lua#L183-L184

Duplicated Origin header

Logs from server
./lib/util.lua:34: attempt to call method 'gsub' (a nil value)
"\nstack traceback:
    \n\t./lib/util.lua:34: in function 'domain_name'
    \n\t./app.lua:187: in function 'filter'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:22: in function 'run_before_filter'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:176: in function 'resolve'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:216: in function </usr/local/share/lua/5.1/lapis/application.lua:214>
    \n\t[C]: in function 'xpcall'
    \n\t/usr/local/share/lua/5.1/lapis/application.lua:214: in function 'dispatch'
    \n\t/usr/local/share/lua/5.1/lapis/nginx.lua:231: in function 'serve'
    \n\tcontent_by_lua(nginx.conf.d/locations.conf:32):2: in main chunk"

Related sources:

https://github.com/snap-cloud/snapCloud/blob/b3d2a4c048ab8b0df1f936c47d942c0790da8034/app.lua#L187

https://github.com/snap-cloud/snapCloud/blob/b3d2a4c048ab8b0df1f936c47d942c0790da8034/lib/util.lua#L34

Steps to reproduce

Steps:

  1. Prepare project according to INSTALL.md
  2. Send an HTTP-packet with a duplicated Accept header: curl -H "Accept: application/json" -H "Accept: application/json" 127.0.0.1:8080
  3. Send an HTTP-packet with a duplicated Content-Type header: curl -H "Content-Type: application/json" -H "Content-Type: application/json" 127.0.0.1:8080
  4. Send an HTTP-packet with a duplicated Origin header: curl -H "Origin: localhost" -H "Origin: localhost" 127.0.0.1:8080

Misc

The HTTP packet I provided may be somewhat of invalid. Nevertheless, I think that SnapCloud's Lua scripts should not crash even on the invalid HTTP packet. Thus, I consider that it is a bug.

Toliak avatar Mar 09 '25 14:03 Toliak

Thanks for the report.

Yes, this is a bit of odd/unexpected behavior. However, there's a bunch of other higher priority items, so I don't think we will get to this very quickly. I'll babe the issue open though.

cycomachead avatar Mar 09 '25 21:03 cycomachead