Codebase list lua-http / 033a0c5
Update upstream source from tag 'upstream/0.4' Update to upstream version '0.4' with Debian dir 472e500bfc6ec488143d4f0543629c3d9ef80248 Santiago Ruano Rincón 3 years ago
23 changed file(s) with 303 addition(s) and 174 deletion(s). Raw diff Collapse all Expand all
0 name: ci
1
2 on:
3 pull_request: {}
4 push:
5 branches: [ $default-branch ]
6
7 jobs:
8 luacheck:
9 runs-on: ubuntu-latest
10 steps:
11 - uses: actions/checkout@v2
12 with:
13 path: lua-http
14 - uses: leafo/gh-actions-lua@v8.0.0
15 - uses: leafo/gh-actions-luarocks@v4.0.0
16 - name: install-tooling
17 run: luarocks install luacheck
18 - name: luacheck
19 run: |
20 cd lua-http
21 luacheck .
22
23 test:
24 runs-on: ubuntu-latest
25 strategy:
26 matrix:
27 luaVersion:
28 - "5.1"
29 - "5.2"
30 - "5.3"
31 - "5.4"
32 - luajit-2.0.5
33 - luajit-2.1.0-beta3
34 luaCompileFlags: [""]
35 zlib: ["", "lzlib", "lua-zlib"]
36 remove_compat53: [false]
37
38 exclude:
39 # lzlib doesn't support Lua 5.4+
40 - luaVersion: "5.4"
41 zlib: "lzlib"
42 include:
43 - luaVersion: "5.3"
44 luaCompileFlags: LUA_CFLAGS="-DLUA_INT_TYPE=LUA_INT_INT"
45 - luaVersion: "5.3"
46 remove_compat53: true
47
48 steps:
49 - uses: actions/checkout@v2
50 with:
51 path: lua-http
52 - uses: leafo/gh-actions-lua@v8.0.0
53 with:
54 luaVersion: ${{ matrix.luaVersion }}
55 - uses: leafo/gh-actions-luarocks@v4.0.0
56 - name: install-tooling
57 run: |
58 luarocks install luacov-coveralls
59 luarocks install busted
60 - name: install-dependencies
61 run: |
62 cd lua-http
63 luarocks install --only-deps http-scm-0.rockspec
64
65 - name: install-lzlib
66 if: matrix.zlib == 'lzlib'
67 run: luarocks install lzlib
68 - name: install-lua-zlib
69 if: matrix.zlib == 'lua-zlib'
70 run: luarocks install lua-zlib
71
72 - name: remove-compat53
73 if: matrix.remove_compat53
74 run: luarocks remove compat53
75
76 - name: test
77 run: |
78 cd lua-http
79 busted -c -o utfTerminal
80
81 - name: coveralls
82 continue-on-error: true
83 env:
84 COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
85 run: |
86 cd lua-http
87 luacov-coveralls -v
88
89 typedlua:
90 runs-on: ubuntu-latest
91 steps:
92 - uses: actions/checkout@v2
93 with:
94 path: lua-http
95 - uses: leafo/gh-actions-lua@v8.0.0
96 with:
97 luaVersion: "5.3" # tlc doesn't work with 5.4+
98 - uses: leafo/gh-actions-luarocks@v4.0.0
99 - name: install-tooling
100 run: luarocks install https://raw.githubusercontent.com/andremm/typedlua/master/typedlua-scm-1.rockspec
101 - name: install-dependencies
102 run: |
103 cd lua-http
104 luarocks install --only-deps http-scm-0.rockspec
105 - name: typedlua
106 run: |
107 cd lua-http
108 tlc -o /dev/null spec/require-all.lua
+0
-63
.travis.yml less more
0 language: python
1
2 sudo: false
3
4 env:
5 matrix:
6 - LUA="lua 5.1"
7 - LUA="lua 5.1" ZLIB=lzlib
8 - LUA="lua 5.1" ZLIB=lua-zlib
9 - LUA="lua 5.2"
10 - LUA="lua 5.2" ZLIB=lzlib
11 - LUA="lua 5.2" ZLIB=lua-zlib
12 - LUA="lua 5.3"
13 - LUA="lua 5.3" ZLIB=lzlib
14 - LUA="lua 5.3" ZLIB=lua-zlib
15 - LUA="lua 5.3" COMPAT53=no
16 - LUA="lua 5.3" LUA_CFLAGS="-DLUA_INT_TYPE=LUA_INT_INT"
17 - LUA="luajit @"
18 - LUA="luajit @" ZLIB=lzlib
19 - LUA="luajit @" ZLIB=lua-zlib
20 - LUA="luajit 2.0"
21 - LUA="luajit 2.0" ZLIB=lzlib
22 - LUA="luajit 2.0" ZLIB=lua-zlib
23 - LUA="luajit 2.1"
24 - LUA="luajit 2.1" ZLIB=lzlib
25 - LUA="luajit 2.1" ZLIB=lua-zlib
26
27 branches:
28 only:
29 - master
30
31 before_install:
32 - pip install hererocks
33 - hererocks ~/hererocks -r^ --$LUA --cflags=$LUA_CFLAGS
34 - export PATH=$PATH:~/hererocks/bin
35 - eval $(luarocks path --bin)
36 - luarocks install luacheck
37 - luarocks install https://raw.githubusercontent.com/andremm/typedlua/master/typedlua-scm-1.rockspec
38 - luarocks install luacov-coveralls
39 - luarocks install busted
40
41 install:
42 - luarocks install --only-deps http-scm-0.rockspec
43 - if [ "$ZLIB" = "lzlib" ]; then luarocks install lzlib; fi
44 - if [ "$ZLIB" = "lua-zlib" ]; then luarocks install lua-zlib; fi
45 - if [ "$COMPAT53" = "no" ]; then luarocks remove compat53; fi
46
47 script:
48 - luacheck .
49 - tlc -o /dev/null spec/require-all.lua
50 - busted -c
51
52 after_success:
53 - luacov-coveralls -v
54
55 notifications:
56 email:
57 on_success: change
58 on_failure: always
59
60 cache:
61 directories:
62 - $HOME/.cache/hererocks
00 The MIT License (MIT)
11
2 Copyright (c) 2015-2019 Daurnimator
2 Copyright (c) 2015-2021 Daurnimator
33
44 Permission is hereby granted, free of charge, to any person obtaining a copy
55 of this software and associated documentation files (the "Software"), to deal
0 0.4 - 2021-02-06
1
2 - Support multiple elliptic curves under OpenSSL 1.1.1+ (#150)
3 - Improve support for Lua 5.4 (not longer require bit library to be installed) (#180)
4 - Ignore delayed RST_STREAM frames in HTTP 2 (#145)
5
6
07 0.3 - 2019-02-13
18
29 - Fix incorrect Sec-WebSocket-Protocol negotiation
1616
1717 ## Status
1818
19 [![Build Status](https://travis-ci.org/daurnimator/lua-http.svg)](https://travis-ci.org/daurnimator/lua-http)
19 [![Build Status](https://github.com/daurnimator/lua-http/workflows/ci/badge.svg)](https://github.com/daurnimator/lua-http/actions?query=workflow%3Aci)
2020 [![Coverage Status](https://coveralls.io/repos/daurnimator/lua-http/badge.svg?branch=master&service=github)](https://coveralls.io/github/daurnimator/lua-http?branch=master)
2121 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/108/badge)](https://bestpractices.coreinfrastructure.org/projects/108)
2222
112112
113113 ### `h1_connection:read_request_line(timeout)` <!-- --> {#http.h1_connection:read_request_line}
114114
115 Reads a request line from the socket. Returns the request method, requested path and HTTP version for an incoming request. `:read_request_line()` yields until a `"\r\n"` terminated chunk is received, or `timeout` is exceeded. If the incoming chunk is not a valid HTTP request line, `nil` is returned. On error, returns `nil`, an error message and an error number.
115 Reads a request line from the socket. Returns the request method, request target and HTTP version for an incoming request. `:read_request_line()` yields until a `"\r\n"` terminated chunk is received, or `timeout` is exceeded. If the incoming chunk is not a valid HTTP request line, `nil` is returned. On error, returns `nil`, an error message and an error number.
116116
117117
118118 ### `h1_connection:read_status_line(timeout)` <!-- --> {#http.h1_connection:read_status_line}
145145 Reads the next available line of data from the request and returns the chunk and any chunk extensions. This function will yield until chunk size is received or `timeout` is exceeded. If the chunk size is indicated as `0` then `false` and any chunk extensions are returned. Returns `nil`, an error message and an error number if there was an error reading reading the chunk header or the socket.
146146
147147
148 ### `h1_connection:write_request_line(method, path, httpversion, timeout)` <!-- --> {#http.h1_connection:write_request_line}
148 ### `h1_connection:write_request_line(method, target, httpversion, timeout)` <!-- --> {#http.h1_connection:write_request_line}
149149
150150 Writes the opening HTTP 1.x request line for a new request to the socket buffer. Yields until success or `timeout`. If the write fails, returns `nil`, an error message and an error number.
151151
66 This means we can ignore the differences between bit libraries.
77 ]]
88
9 -- Lua 5.3 has built-in bit operators, wrap them in a function.
10 if _VERSION == "Lua 5.3" then
9 -- Lua 5.1 didn't have `load` or bitwise operators, just let it fall through.
10 if _VERSION ~= "Lua 5.1" then
11 -- Lua 5.3+ has built-in bit operators, wrap them in a function.
1112 -- Use debug.getinfo to get correct file+line numbers for loaded snippet
1213 local info = debug.getinfo(1, "Sl")
13 return assert(load(("\n"):rep(info.currentline+1)..[[return {
14 local has_bitwise, bitwise = pcall(load(("\n"):rep(info.currentline+1)..[[return {
1415 band = function(a, b) return a & b end;
1516 bor = function(a, b) return a | b end;
1617 bxor = function(a, b) return a ~ b end;
17 }]], info.source))()
18 }]], info.source))
19 if has_bitwise then
20 return bitwise
21 end
1822 end
1923
2024 -- The "bit" library that comes with luajit
166166 end
167167 return nil, err, errno
168168 end
169 local method, path, httpversion = line:match("^(%w+) (%S+) HTTP/(1%.[01])\r\n$")
169 local method, target, httpversion = line:match("^(%w+) (%S+) HTTP/(1%.[01])\r\n$")
170170 if not method then
171171 self.socket:seterror("r", ce.EILSEQ)
172172 local ok, errno2 = self.socket:unget(line)
182182 return nil, onerror(self.socket, "read_request_line", ce.EILSEQ)
183183 end
184184 httpversion = httpversion == "1.0" and 1.0 or 1.1 -- Avoid tonumber() due to locale issues
185 return method, path, httpversion
185 return method, target, httpversion
186186 end
187187
188188 function connection_methods:read_status_line(timeout)
343343 end
344344 end
345345
346 function connection_methods:write_request_line(method, path, httpversion, timeout)
346 function connection_methods:write_request_line(method, target, httpversion, timeout)
347347 assert(method:match("^[^ \r\n]+$"))
348 assert(path:match("^[^ \r\n]+$"))
348 assert(target:match("^[^ \r\n]+$"))
349349 assert(httpversion == 1.0 or httpversion == 1.1)
350 local line = string.format("%s %s HTTP/%s\r\n", method, path, httpversion == 1.0 and "1.0" or "1.1")
350 local line = string.format("%s %s HTTP/%s\r\n", method, target, httpversion == 1.0 and "1.0" or "1.1")
351351 local ok, err, errno = self.socket:xwrite(line, "f", timeout)
352352 if not ok then
353353 return nil, err, errno
266266 if self.state == "half closed (local)" then
267267 return nil
268268 end
269 local method, path, httpversion = self.connection:read_request_line(0)
269 local method, target, httpversion = self.connection:read_request_line(0)
270270 if method == nil then
271271 if httpversion == ce.ETIMEDOUT then
272272 timeout = deadline and deadline-monotime()
274274 return self:read_headers(deadline and deadline-monotime())
275275 end
276276 end
277 return nil, path, httpversion
277 return nil, target, httpversion
278278 end
279279 self.req_method = method
280280 self.peer_version = httpversion
281281 headers = new_headers()
282282 headers:append(":method", method)
283283 if method == "CONNECT" then
284 headers:append(":authority", path)
284 headers:append(":authority", target)
285285 else
286 headers:append(":path", path)
286 headers:append(":path", target)
287287 end
288288 headers:append(":scheme", self:checktls() and "https" or "http")
289289 self:set_state("open")
481481 [":path"] = true;
482482 [":scheme"] = true;
483483 [":status"] = true;
484 [":protocol"] = true; -- from RFC 8441
484485 -- fields written manually in :write_headers
485486 ["connection"] = true;
486487 ["content-length"] = true;
563564 if self.state == "idle" then
564565 method = assert(headers:get(":method"), "missing method")
565566 self.req_method = method
566 local path
567 local target
567568 if method == "CONNECT" then
568 path = assert(headers:get(":authority"), "missing authority")
569 target = assert(headers:get(":authority"), "missing authority")
569570 assert(not headers:has(":path"), "CONNECT requests should not have a path")
570571 else
571572 -- RFC 7230 Section 5.4: A client MUST send a Host header field in all HTTP/1.1 request messages.
572573 assert(self.connection.version < 1.1 or headers:has(":authority"), "missing authority")
573 path = assert(headers:get(":path"), "missing path")
574 target = assert(headers:get(":path"), "missing path")
574575 end
575576 if self.connection.req_locked then
576577 -- Wait until previous request has been fully written
584585 self.connection.pipeline:push(self)
585586 self.connection.req_locked = self
586587 -- write request line
587 local ok, err, errno = self.connection:write_request_line(method, path, self.connection.version, 0)
588 local ok, err, errno = self.connection:write_request_line(method, target, self.connection.version, 0)
588589 if not ok then
589590 return nil, err, errno
590591 end
689689 end
690690 if stream.state == "idle" then
691691 return nil, h2_errors.PROTOCOL_ERROR:new_traceback("'RST_STREAM' frames MUST NOT be sent for a stream in the 'idle' state"), ce.EILSEQ
692 elseif stream.state == "closed" then
693 -- probably a delayed RST_STREAM, ignore
694 return true
692695 end
693696
694697 local err_code = sunpack(">I4", payload)
13821385 if max_available < (#payload - sent) then
13831386 if max_available > 0 then
13841387 -- send partial payload
1385 local ok, err, errno = self:write_data_frame(payload:sub(sent+1, sent+max_available), false, timeout)
1388 local ok, err, errno = self:write_data_frame(payload:sub(sent+1, sent+max_available), false, false, timeout)
13861389 if not ok then
13871390 return nil, err, errno
13881391 end
22
33 Design criteria:
44 - the same header field is allowed more than once
5 - must be able to fetch seperate occurences (important for some headers e.g. Set-Cookie)
6 - optionally available as comma seperated list
5 - must be able to fetch separate occurences (important for some headers e.g. Set-Cookie)
6 - optionally available as comma separated list
77 - http2 adds flag to headers that they should never be indexed
88 - header order should be recoverable
99
5656 end
5757 end
5858 end
59 if scheme == "http" or scheme == "ws" then
59 if scheme == "http" then
6060 if self.http_proxy then
6161 return self.http_proxy
6262 end
63 elseif scheme == "https" or scheme == "wss" then
63 elseif scheme == "https" then
6464 if self.https_proxy then
6565 return self.https_proxy
6666 end
7676 path = path .. "?" .. uri_t.query
7777 end
7878 headers:upsert(":path", path)
79 if scheme == "wss" then
80 scheme = "https"
81 elseif scheme == "ws" then
82 scheme = "http"
83 end
7984 headers:upsert(":scheme", scheme)
8085 end
8186 if uri_t.userinfo then
9499 return setmetatable({
95100 host = host;
96101 port = port;
97 tls = (scheme == "https" or scheme == "wss");
102 tls = (scheme == "https");
98103 headers = headers;
99104 body = nil;
100105 }, request_mt)
208213 if not is_connect then
209214 new_req.headers:upsert(":scheme", new_scheme)
210215 end
211 if new_scheme == "https" or new_scheme == "wss" then
216 if new_scheme == "https" then
212217 new_req.tls = true
213 elseif new_scheme == "http" or new_scheme == "ws" then
218 elseif new_scheme == "http" then
214219 new_req.tls = false
215220 else
216221 return nil, "unknown scheme", ce.EINVAL
351356 local host = self.host
352357 local port = self.port
353358 local tls = self.tls
359 local version = self.version
354360
355361 -- RFC 6797 Section 8.3
356362 if not tls and self.hsts and self.hsts:check(host) then
438444 tls = tls;
439445 ctx = self.ctx;
440446 sendname = self.sendname;
441 version = self.version;
447 version = version;
442448 h2_settings = default_h2_settings;
443449 }, deadline and deadline-monotime())
444450 if connection == nil then
474480 tls = tls;
475481 ctx = self.ctx;
476482 sendname = self.sendname ~= nil and self.sendname or host;
477 version = self.version;
483 version = version;
478484 h2_settings = default_h2_settings;
479485 }, deadline and deadline-monotime())
480486 if connection == nil then
495501 tls = tls;
496502 ctx = self.ctx;
497503 sendname = self.sendname;
498 version = self.version;
504 version = version;
499505 h2_settings = default_h2_settings;
500506 }, deadline and deadline-monotime())
501507 if connection == nil then
754754 local ctx = openssl_ctx.new("TLS", false)
755755 ctx:setCipherList(intermediate_cipher_list)
756756 ctx:setOptions(default_tls_options)
757 ctx:setEphemeralKey(openssl_pkey.new{ type = "EC", curve = "prime256v1" })
757 if ctx.setGroups then
758 ctx:setGroups("P-521:P-384:P-256")
759 else
760 ctx:setEphemeralKey(openssl_pkey.new{ type = "EC", curve = "prime256v1" })
761 end
758762 local store = ctx:getStore()
759763 store:addDefaults()
760764 ctx:setVerify(openssl_ctx.VERIFY_PEER)
765769 local ctx = openssl_ctx.new("TLS", true)
766770 ctx:setCipherList(intermediate_cipher_list)
767771 ctx:setOptions(default_tls_options)
768 ctx:setEphemeralKey(openssl_pkey.new{ type = "EC", curve = "prime256v1" })
772 if ctx.setGroups then
773 ctx:setGroups("P-521:P-384:P-256")
774 else
775 ctx:setEphemeralKey(openssl_pkey.new{ type = "EC", curve = "prime256v1" })
776 end
769777 return ctx
770778 end
771779
44
55 return {
66 name = "lua-http";
7 version = "0.3";
7 version = "0.4";
88 }
544544
545545 local function new_from_uri(uri, protocols)
546546 local request = http_request.new_from_uri(uri)
547 local scheme = request.headers:get(":scheme")
548 assert(scheme == "ws" or scheme == "wss", "scheme not websocket")
549547 local self = new("client")
550548 self.request = request
551549 self.request.version = 1.1
+0
-58
http-0.3-0.rockspec less more
0 package = "http"
1 version = "0.3-0"
2
3 description = {
4 summary = "HTTP library for Lua";
5 homepage = "https://github.com/daurnimator/lua-http";
6 license = "MIT";
7 }
8
9 source = {
10 url = "https://github.com/daurnimator/lua-http/archive/v0.3.zip";
11 dir = "lua-http-0.3";
12 }
13
14 dependencies = {
15 "lua >= 5.1";
16 "compat53 >= 0.3"; -- Only if lua < 5.3
17 "bit32"; -- Only if lua == 5.1
18 "cqueues >= 20161214";
19 "luaossl >= 20161208";
20 "basexx >= 0.2.0";
21 "lpeg";
22 "lpeg_patterns >= 0.5";
23 "binaryheap >= 0.3";
24 "fifo";
25 -- "psl"; -- Optional
26 }
27
28 build = {
29 type = "builtin";
30 modules = {
31 ["http.bit"] = "http/bit.lua";
32 ["http.client"] = "http/client.lua";
33 ["http.connection_common"] = "http/connection_common.lua";
34 ["http.cookie"] = "http/cookie.lua";
35 ["http.h1_connection"] = "http/h1_connection.lua";
36 ["http.h1_reason_phrases"] = "http/h1_reason_phrases.lua";
37 ["http.h1_stream"] = "http/h1_stream.lua";
38 ["http.h2_connection"] = "http/h2_connection.lua";
39 ["http.h2_error"] = "http/h2_error.lua";
40 ["http.h2_stream"] = "http/h2_stream.lua";
41 ["http.headers"] = "http/headers.lua";
42 ["http.hpack"] = "http/hpack.lua";
43 ["http.hsts"] = "http/hsts.lua";
44 ["http.proxies"] = "http/proxies.lua";
45 ["http.request"] = "http/request.lua";
46 ["http.server"] = "http/server.lua";
47 ["http.socks"] = "http/socks.lua";
48 ["http.stream_common"] = "http/stream_common.lua";
49 ["http.tls"] = "http/tls.lua";
50 ["http.util"] = "http/util.lua";
51 ["http.version"] = "http/version.lua";
52 ["http.websocket"] = "http/websocket.lua";
53 ["http.zlib"] = "http/zlib.lua";
54 ["http.compat.prosody"] = "http/compat/prosody.lua";
55 ["http.compat.socket"] = "http/compat/socket.lua";
56 };
57 }
0 package = "http"
1 version = "0.4-0"
2
3 description = {
4 summary = "HTTP library for Lua";
5 homepage = "https://github.com/daurnimator/lua-http";
6 license = "MIT";
7 }
8
9 source = {
10 url = "https://github.com/daurnimator/lua-http/archive/v0.4.zip";
11 dir = "lua-http-0.4";
12 }
13
14 dependencies = {
15 "lua >= 5.1";
16 "compat53 >= 0.3"; -- Only if lua < 5.3
17 "bit32"; -- Only if lua == 5.1
18 "cqueues >= 20161214";
19 "luaossl >= 20161208";
20 "basexx >= 0.2.0";
21 "lpeg";
22 "lpeg_patterns >= 0.5";
23 "binaryheap >= 0.3";
24 "fifo";
25 -- "psl"; -- Optional
26 }
27
28 build = {
29 type = "builtin";
30 modules = {
31 ["http.bit"] = "http/bit.lua";
32 ["http.client"] = "http/client.lua";
33 ["http.connection_common"] = "http/connection_common.lua";
34 ["http.cookie"] = "http/cookie.lua";
35 ["http.h1_connection"] = "http/h1_connection.lua";
36 ["http.h1_reason_phrases"] = "http/h1_reason_phrases.lua";
37 ["http.h1_stream"] = "http/h1_stream.lua";
38 ["http.h2_connection"] = "http/h2_connection.lua";
39 ["http.h2_error"] = "http/h2_error.lua";
40 ["http.h2_stream"] = "http/h2_stream.lua";
41 ["http.headers"] = "http/headers.lua";
42 ["http.hpack"] = "http/hpack.lua";
43 ["http.hsts"] = "http/hsts.lua";
44 ["http.proxies"] = "http/proxies.lua";
45 ["http.request"] = "http/request.lua";
46 ["http.server"] = "http/server.lua";
47 ["http.socks"] = "http/socks.lua";
48 ["http.stream_common"] = "http/stream_common.lua";
49 ["http.tls"] = "http/tls.lua";
50 ["http.util"] = "http/util.lua";
51 ["http.version"] = "http/version.lua";
52 ["http.websocket"] = "http/websocket.lua";
53 ["http.zlib"] = "http/zlib.lua";
54 ["http.compat.prosody"] = "http/compat/prosody.lua";
55 ["http.compat.socket"] = "http/compat/socket.lua";
56 };
57 }
2929 local stream = client:new_stream()
3030 client:shutdown()
3131 local headers = new_headers()
32 headers:append(":method", "GET")
33 headers:append(":scheme", "http")
3234 headers:append(":authority", "myauthority")
33 headers:append(":method", "GET")
3435 headers:append(":path", "/a")
3536 assert.same(ce.EPIPE, select(3, stream:write_headers(headers, true)))
3637 client:close()
4243 cq:wrap(function()
4344 local stream = client:new_stream()
4445 local req_headers = new_headers()
46 req_headers:append(":method", "GET")
47 req_headers:append(":scheme", "http")
4548 req_headers:append(":authority", "myauthority")
46 req_headers:append(":method", "GET")
4749 req_headers:append(":path", "/a")
4850 assert(stream:write_headers(req_headers, true))
4951 local res_headers = assert(stream:get_headers())
9092 local server, client = new_pair(1.1)
9193 local stream = client:new_stream()
9294 local headers = new_headers()
95 headers:append(":method", "GET")
96 headers:append(":scheme", "http")
9397 headers:append(":authority", "myauthority")
94 headers:append(":method", "GET")
9598 headers:append(":path", "/a")
9699 assert(stream:write_headers(headers, true))
97100 local cq = cqueues.new():wrap(function()
108111 cq:wrap(function()
109112 local stream = client:new_stream()
110113 local req_headers = new_headers()
114 req_headers:append(":method", "GET")
115 req_headers:append(":scheme", "http")
111116 req_headers:append(":authority", "myauthority")
112 req_headers:append(":method", "GET")
113117 req_headers:append(":path", "/a")
114118 assert(stream:write_headers(req_headers, true))
115119 local res_headers = assert(stream:get_headers())
134138 cq:wrap(function()
135139 local stream = client:new_stream()
136140 local req_headers = new_headers()
141 req_headers:append(":method", "GET")
142 req_headers:append(":scheme", "http")
137143 req_headers:append(":authority", "myauthority")
138 req_headers:append(":method", "GET")
139144 req_headers:append(":path", "/a")
140145 assert(stream:write_headers(req_headers, true))
141146 assert(stream:get_headers())
165170 cq:wrap(function()
166171 local stream = client:new_stream()
167172 local headers = new_headers()
173 headers:append(":method", "GET")
174 headers:append(":scheme", "http")
168175 headers:append(":authority", "myauthority")
169 headers:append(":method", "GET")
170176 headers:append(":path", "/a")
171177 headers:append("transfer-encoding", "chunked")
172178 assert(stream:write_headers(headers, false))
216222 cq:wrap(function()
217223 local stream = client:new_stream()
218224 local headers = new_headers()
225 headers:append(":method", "GET")
226 headers:append(":scheme", "http")
219227 headers:append(":authority", "myauthority")
220 headers:append(":method", "GET")
221228 headers:append(":path", "/a")
222229 headers:append("transfer-encoding", "chunked")
223230 assert(stream:write_headers(headers, false))
247254 do
248255 local stream = client:new_stream()
249256 local headers = new_headers()
257 headers:append(":method", "GET")
258 headers:append(":scheme", "http")
250259 headers:append(":authority", "myauthority")
251 headers:append(":method", "GET")
252260 headers:append(":path", "/a")
253261 headers:append("content-length", "100")
254262 assert(stream:write_headers(headers, false))
257265 do
258266 local stream = client:new_stream()
259267 local headers = new_headers()
268 headers:append(":method", "GET")
269 headers:append(":scheme", "http")
260270 headers:append(":authority", "myauthority")
261 headers:append(":method", "GET")
262271 headers:append(":path", "/b")
263272 headers:append("content-length", "0")
264273 assert(stream:write_headers(headers, true))
312321 if client_sync then client_sync:wait() end
313322 local a = client:new_stream()
314323 local ah = new_headers()
324 ah:append(":method", "GET")
325 ah:append(":scheme", "http")
315326 ah:append(":authority", "myauthority")
316 ah:append(":method", "GET")
317327 ah:append(":path", "/a")
318328 assert(a:write_headers(ah, true))
319329 end)
321331 client_sync:signal(); client_sync = nil;
322332 local b = client:new_stream()
323333 local bh = new_headers()
334 bh:append(":method", "POST")
335 bh:append(":scheme", "http")
324336 bh:append(":authority", "myauthority")
325 bh:append(":method", "POST")
326337 bh:append(":path", "/b")
327338 assert(b:write_headers(bh, false))
328339 cqueues.sleep(0.01)
331342 cq:wrap(function()
332343 local c = client:new_stream()
333344 local ch = new_headers()
345 ch:append(":method", "GET")
346 ch:append(":scheme", "http")
334347 ch:append(":authority", "myauthority")
335 ch:append(":method", "GET")
336348 ch:append(":path", "/c")
337349 assert(c:write_headers(ch, true))
338350 end)
374386
375387 do
376388 local h = new_headers()
389 h:append(":method", "POST")
390 h:append(":scheme", "http")
377391 h:append(":authority", "myauthority")
378 h:append(":method", "POST")
379392 h:append(":path", "/")
380393 h:upsert("id", "a")
381394 assert(a:write_headers(h, false))
442455 cq:wrap(function()
443456 local a = client:new_stream()
444457 local h = new_headers()
458 h:append(":method", "POST")
459 h:append(":scheme", "http")
445460 h:append(":authority", "myauthority")
446 h:append(":method", "POST")
447461 h:append(":path", "/a")
448462 h:append("expect", "100-continue")
449463 assert(a:write_headers(h, false))
475489 cq:wrap(function()
476490 local a = client:new_stream()
477491 local h = new_headers()
492 h:append(":method", "GET")
493 h:append(":scheme", "http")
478494 h:append(":authority", "myauthority")
479 h:append(":method", "GET")
480495 h:append(":path", "/")
481496 assert(a:write_headers(h, true))
482497 end)
123123 assert_loop(cq, TEST_TIMEOUT)
124124 assert.truthy(cq:empty())
125125 end)
126 it("ignores delayed RST_STREAM on already closed stream", function()
127 local s, c = new_pair()
128 local cq = cqueues.new()
129 cq:wrap(function()
130 local client_stream = c:new_stream()
131 local req_headers = new_headers()
132 req_headers:append(":method", "GET")
133 req_headers:append(":scheme", "http")
134 req_headers:append(":path", "/")
135 req_headers:append(":authority", "example.com")
136 assert(client_stream:write_headers(req_headers, true))
137 assert(client_stream:get_headers())
138 assert("closed", client_stream.state)
139 -- both sides now have stream in closed state
140 -- send server a RST_STREAM: it should get ignored
141 assert(client_stream:rst_stream("post-closed rst_stream"))
142 assert(c:close())
143 end)
144 cq:wrap(function()
145 local stream = assert(s:get_next_incoming_stream())
146 assert(stream:get_headers())
147 local res_headers = new_headers()
148 res_headers:append(":status", "200")
149 assert(stream:write_headers(res_headers, true))
150 -- both sides now have stream in closed state
151 assert("closed", stream.state)
152 -- process incoming frames until EOF (i.e. drain RST_STREAM)
153 -- the RST_STREAM frame should be ignored.
154 assert(s:loop())
155 assert(s:close())
156 end)
157 cq:wrap(function()
158 assert(s:loop())
159 end)
160 assert_loop(cq, TEST_TIMEOUT)
161 assert.truthy(cq:empty())
162 end)
126163 end)
127164 describe("push_promise", function()
128165 it("permits a simple push promise from server => client", function()
267267 }))
268268 local headers = http_headers.new()
269269 headers:append(":method", "GET")
270 headers:append(":scheme", "http")
270271 headers:append(":path", "/")
271272 headers:append(":authority", "foo")
272273 -- Normal request
1111 end
1212 local function new_request_headers()
1313 local headers = new_headers()
14 headers:append(":method", "GET")
15 headers:append(":scheme", "http")
1416 headers:append(":authority", "myauthority")
15 headers:append(":method", "GET")
1617 headers:append(":path", "/")
1718 return headers
1819 end
9191 end
9292 local correct_headers = http_headers.new()
9393 correct_headers:append(":method", "GET")
94 correct_headers:append(":scheme", "http")
9495 correct_headers:append(":authority", "example.com")
9596 correct_headers:append(":path", "/")
9697 correct_headers:append("upgrade", "websocket")
374375 port = 0;
375376 onstream = function(s, stream)
376377 local headers = assert(stream:get_headers())
378 assert.same("http", headers:get(":scheme"))
377379 local ws = websocket.new_from_stream(stream, headers)
378380 assert(ws:accept())
379381 assert(ws:close())