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

Update llhttp #691

Merged
merged 3 commits into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 78 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,79 @@
# Developer's Certificate of Origin 1.1
# Contributing to Undici

* [Guides](#guides)
* [Update `llhttp`](#update-llhttp)
* [Developer's Certificate of Origin 1.1](#developers-certificate-of-origin)
* [Moderation Policy](#moderation-policy)

<a id="guides"></a>
## Guides

<a id="update-llhttp"></a>
### Update `llhttp`

The HTTP parser used by `undici` is a WebAssembly build of [`llhttp`](https://github.com/nodejs/llhttp).

While the project itself provides a way to compile targeting WebAssembly, at the moment we embed the sources
directly and compile the module in `undici`.

The `deps/llhttp/include` folder contains the C header files, while the `deps/llhttp/src` folder contains
the C source files needed to compile the module.

The `lib/llhttp` folder contains the `.js` transpiled assets required to implement a parser.

The following are the steps required to perform an update.

#### Clone the [llhttp](https://github.com/nodejs/llhttp) project

```bash
git clone git@github.com:nodejs/llhttp.git

cd llhttp
```
#### Checkout a `llhttp` release

```bash
git checkout <tag>
```

#### Install the `llhttp` dependencies

```bash
npm i
```

#### Run the wasm build script

```bash
npm run build-wasm
```

#### Copy the sources to `undici`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these steps could be condensed to:

cp build/llhttp/wasm/* <path-to-undici>/lib/llhttp

If we remove the embedding and use the llhttp project build. Just wanted to say that's an option if this is too clumsy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guide should be revisited if/when we have to modify lhttp sources for whatever reason.


```bash
cp build/wasm/*.js <your-path-to-undici>/lib/llhttp/

cp build/wasm/*.js.map <your-path-to-undici>/lib/llhttp/

cp build/wasm/*.d.ts <your-path-to-undici>/lib/llhttp/

cp src/native/api.c src/native/http.c build/c/llhttp.c <your-path-to-undici>/deps/llhttp/src/

cp src/native/api.h build/llhttp.h <your-path-to-undici>/deps/llhttp/include/
```

#### Build the WebAssembly module in `undici`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this would not be needed of we didn't embed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid embedding as of now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can. We don't currently modify the source files. IMHO is a cleaner approach, as long as we don't have to customize it. One thing to consider is the direction the llhttp project will take towards wasm. For example, what if the only way to access the build would be by installing it as a dependency and use its .js API (as suggested in nodejs/llhttp#93)? Would we be open to that?

But regarding now, we would just have to run build-wasm in llhttp and copy the build/wasm folder contents in lib/llhttp.


> This requires [docker](https://www.docker.com/) installed on your machine.

```bash
cd <your-path-to-undici>

npm run build:wasm
```

<a id="developers-certificate-of-origin"></a>
## Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

Expand All @@ -24,7 +99,8 @@ By making a contribution to this project, I certify that:
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

## Moderation Policy
<a id="moderation-policy"></a>
### Moderation Policy

The [Node.js Moderation Policy] applies to this project.

Expand Down
27 changes: 22 additions & 5 deletions deps/llhttp/include/llhttp.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef INCLUDE_LLHTTP_H_
#define INCLUDE_LLHTTP_H_

#define LLHTTP_VERSION_MAJOR 4
#define LLHTTP_VERSION_MINOR 0
#define LLHTTP_VERSION_MAJOR 5
#define LLHTTP_VERSION_MINOR 1
#define LLHTTP_VERSION_PATCH 0

#ifndef LLHTTP_STRICT_MODE
Expand Down Expand Up @@ -79,7 +79,8 @@ enum llhttp_errno {
HPE_CB_CHUNK_COMPLETE = 20,
HPE_PAUSED = 21,
HPE_PAUSED_UPGRADE = 22,
HPE_USER = 23
HPE_PAUSED_H2_UPGRADE = 23,
HPE_USER = 24
};
typedef enum llhttp_errno llhttp_errno_t;

Expand All @@ -98,7 +99,8 @@ typedef enum llhttp_flags llhttp_flags_t;

enum llhttp_lenient_flags {
LENIENT_HEADERS = 0x1,
LENIENT_CHUNKED_LENGTH = 0x2
LENIENT_CHUNKED_LENGTH = 0x2,
LENIENT_KEEP_ALIVE = 0x4
};
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;

Expand Down Expand Up @@ -190,7 +192,8 @@ typedef enum llhttp_method llhttp_method_t;
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
XX(21, PAUSED, PAUSED) \
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
XX(23, USER, USER) \
XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \
XX(24, USER, USER) \


#define HTTP_METHOD_MAP(XX) \
Expand Down Expand Up @@ -483,6 +486,20 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
LLHTTP_EXPORT
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);


/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0
* requests responses.
*
* Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
* the HTTP request/response after the request/response with `Connection: close`
* and `Content-Length`. This is important to prevent cache poisoning attacks,
* but might interact badly with outdated and insecure clients. With this flag
* the extra request/response will be parsed normally.
*
* **(USE AT YOUR OWN RISK)**
*/
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down
11 changes: 10 additions & 1 deletion deps/llhttp/src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
}
}


void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
Expand All @@ -223,6 +224,14 @@ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
}


void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_KEEP_ALIVE;
} else {
parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;
}
}

/* Callbacks */


Expand Down Expand Up @@ -324,7 +333,7 @@ int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
}


/* Private https://github.com/dnlup/llhttp/blob/undici_wasm/wasm.js*/
/* Private */


void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
Expand Down
Loading