diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index df26884..d0f8add 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -80,23 +80,23 @@ export default defineConfig({ link: '/roadmap/phase-0/stage-0.md', }, { - text: 'Stage 1: TCP server', + text: 'Stage 1: TCP Server', link: '/roadmap/phase-0/stage-1', }, { - text: 'Stage 2: TCP client', + text: 'Stage 2: TCP Client', link: '/roadmap/phase-0/stage-2', }, { - text: 'Stage 3: Epoll', + text: 'Stage 3: Linux epoll', link: '/roadmap/phase-0/stage-3', }, { - text: 'Stage 4: UDP server with multi-threading', + text: 'Stage 4: UDP Multi-threading', link: '/roadmap/phase-0/stage-4', }, { - text: 'Stage 5: TCP proxy', + text: 'Stage 5: TCP Proxy', link: '/roadmap/phase-0/stage-5', }, ], @@ -110,25 +110,29 @@ export default defineConfig({ link: '/roadmap/phase-1/', }, { - text: 'Stage 6: Server & Client module', + text: 'Stage 6: Listener & Connection Modules', link: '/roadmap/phase-1/stage-6', }, { - text: 'Stage 7: Core & Loop module', + text: 'Stage 7: Core & Loop Modules', link: '/roadmap/phase-1/stage-7', }, { - text: 'Stage 8: TCP module', + text: 'Stage 8: Pipe Module', link: '/roadmap/phase-1/stage-8', }, { - text: 'Stage 9: Upstream module', + text: 'Stage 9: Upstream Module', link: '/roadmap/phase-1/stage-9', }, { text: 'Stage 10: File module', link: '/roadmap/phase-1/stage-10', }, + { + text: 'Stage 11: Session Module', + link: '/roadmap/phase-1/stage-11', + }, ], }, { @@ -140,21 +144,21 @@ export default defineConfig({ link: '/roadmap/phase-2/', }, { - text: 'Stage 11: HTTP parser', - link: '/roadmap/phase-2/stage-11', - }, - { - text: 'Stage 12: HTTP req & HTTP res', + text: 'Stage 12: HTTP Request Module', link: '/roadmap/phase-2/stage-12', }, { - text: 'Stage 13: Config & Session module', + text: 'Stage 13: HTTP Response Module', link: '/roadmap/phase-2/stage-13', }, { - text: 'Stage 14: HTTP Spec', + text: 'Stage 14: Config Module', link: '/roadmap/phase-2/stage-14', }, + { + text: 'Stage 15: HTTP Specification', + link: '/roadmap/phase-2/stage-15', + }, ], }, { @@ -166,25 +170,25 @@ export default defineConfig({ link: '/roadmap/phase-3/', }, { - text: 'Stage 15: IP whitelist & blacklist', - link: '/roadmap/phase-3/stage-15', - }, - { - text: 'Stage 16: Directory browsing', + text: 'Stage 16: Directory Browsing', link: '/roadmap/phase-3/stage-16', }, { - text: 'Stage 17: Compression', + text: 'Stage 17: IP Whitelist/Blacklist', link: '/roadmap/phase-3/stage-17', }, { - text: 'Stage 18: Load balancing', + text: 'Stage 18: Gzip Compression', link: '/roadmap/phase-3/stage-18', }, { - text: 'Stage 19: Rate limiting & timeouts', + text: 'Stage 19: Load Balancing', link: '/roadmap/phase-3/stage-19', }, + { + text: 'Stage 20: Request timeouts', + link: '/roadmap/phase-3/stage-20', + }, ], }, { @@ -196,17 +200,21 @@ export default defineConfig({ link: '/roadmap/phase-4/', }, { - text: 'Stage 20: TLS', - link: '/roadmap/phase-4/stage-20', - }, - { - text: 'Stage 21: Caching', + text: 'Stage 21: Metrics', link: '/roadmap/phase-4/stage-21', }, { - text: 'Stage 22: Multiprocess Architecture', + text: 'Stage 22: Multiprocess', link: '/roadmap/phase-4/stage-22', }, + { + text: 'Stage 23: Caching', + link: '/roadmap/phase-4/stage-23', + }, + { + text: 'Stage 24: Transport Layer Security (TLS)', + link: '/roadmap/phase-4/stage-24', + }, ], }, ], diff --git a/docs/guides/resources/architecture.md b/docs/guides/resources/architecture.md index c2827f2..a86a055 100644 --- a/docs/guides/resources/architecture.md +++ b/docs/guides/resources/architecture.md @@ -51,7 +51,7 @@ A detailed view of the _structs_ and _functions_ present in each module will be ### `xps_core` -The `xps_core` module serves as the container to which [instances]() of all other modules are attached. It can be thought of as an instance of eXpServer. +The `xps_core` module serves as the container to which [instances]() of all other modules are attached. It can be thought of as an instance of eXpServer itself. ### `xps_loop` @@ -59,7 +59,7 @@ The `xps_loop` module contains the [event loop](https://en.wikipedia.org/wiki/Ev ### `xps_config` -The `xps_config` module is responsible for reading and parsing the configuration file, the path to which is provided as a [command line argument](https://en.wikipedia.org/wiki/Command-line_interface#Arguments). The configuration file is written and parsed using [Lua]() into a configuration _struct_ and stored in the `xps_core` instance. +The `xps_config` module is responsible for reading and parsing the configuration file, the path to which is provided as a [command line argument](https://en.wikipedia.org/wiki/Command-line_interface#Arguments). The configuration file will be a JSON file with a specific structure. It is parsed using [parson](https://github.com/kgabis/parson), a 3rd party JSON parser. After parsing, it is stored in the `xps_core` instance as a configuration _struct_. ### `xps_listener` @@ -93,7 +93,7 @@ Read more about _pipes_ below. ## xps_pipes -Pipes in eXpServer are the links that allow uni-directional [controlled flow]() of bytes from one node to another. An xps_pipe is an instance of `xps_pipe_t` type and is attached to a source instance of type `xps_pipe_source_t` on one end and a sink instance of type `xps_pipe_sink_t` on the other. +Pipes in eXpServer are the links that allow uni-directional [controlled flow]() of bytes from one node to another. An `xps_pipe` is an instance of `xps_pipe_t` type and is attached to a source instance of type `xps_pipe_source_t` on one end and a sink instance of type `xps_pipe_sink_t` on the other. Let us take a look at an example @@ -124,7 +124,7 @@ Now let us look at how this works In our case, - If the source is writing to the pipe faster than the sink is reading it, then the pipe buffer will fill up and reach above the buffer threshold. If that happens, even if the source is ready, `handler_cb()` on the source will not be invoked, there by ‘blocking’ the source from writing to the pipe. -- Similarly, if the sink is reading from the pipe faster than the source is writing to it, then, when the pipe becomes empty the `handler_cb()` on the sink will not be invoked even if the sink is ready, there by ‘blocking’ the sink from reading from the pipe +- Similarly, if the sink is reading from the pipe faster than the source is writing to it, then, when the pipe becomes empty, the `handler_cb()` on the sink will not be invoked even if the sink is ready, thereby ‘blocking’ the sink from reading from the pipe ### Isolation of Logic diff --git a/docs/roadmap/index.md b/docs/roadmap/index.md index 2a9c50e..43a7d20 100644 --- a/docs/roadmap/index.md +++ b/docs/roadmap/index.md @@ -29,32 +29,34 @@ The eXpServer project comprises 22 stages, organized into 5 phases. Prior to the ### Phase 1: Building the core of eXpServer by creating reusable modules - [Overview](phase-1/) -- [Stage 6: Server & Client Modules](phase-1/stage-6) +- [Stage 6: Listener & Connection Modules](phase-1/stage-6) - [Stage 7: Core & Loop Modules](phase-1/stage-7) -- [Stage 8: TCP Module](phase-1/stage-8) +- [Stage 8: Pipe Module](phase-1/stage-8) - [Stage 9: Upstream Module](phase-1/stage-9) - [Stage 10: File Module](phase-1/stage-10) +- [Stage 11: Session Module](phase-1/stage-11) ### Phase 2: Implementing HTTP support - [Overview](phase-2/) -- [Stage 11: HTTP Parser](phase-2/stage-11) -- [Stage 12: HTTP Req & Res Modules](phase-2/stage-12) -- [Stage 13: Config & Session Modules](phase-2/stage-13) -- [Stage 14: HTTP Specification](phase-2/stage-14) +- [Stage 12: HTTP Request Module](phase-2/stage-12) +- [Stage 13: HTTP Response Module](phase-2/stage-13) +- [Stage 14: Config Module](phase-2/stage-14) +- [Stage 15: HTTP Specification](phase-2/stage-15) ### Phase 3: Adding features to eXpServer - [Overview](phase-3/) -- [Stage 15: IP Whitelist/Blacklist](phase-3/stage-15) - [Stage 16: Directory Browsing](phase-3/stage-16) -- [Stage 17: Gzip Compression](phase-3/stage-17) -- [Stage 18: Load Balancing](phase-3/stage-18) -- [Stage 19: Rate Limiting & Timeout](phase-3/stage-19) +- [Stage 17: IP Whitelist/Blacklist](phase-3/stage-17) +- [Stage 18: Gzip Compression](phase-3/stage-18) +- [Stage 19: Load Balancing](phase-3/stage-19) +- [Stage 20: Request timeouts](phase-3/stage-20) ### Phase 4: Advanced features and multiprocess architecture - [Overview](phase-4/) -- [Stage 20: Transport Layer Security (TLS)](phase-4/stage-20) -- [Stage 21: Caching](phase-4/stage-21) -- [Stage 22: Multiprocess Architecture](phase-4/stage-22) +- [Stage 21: Metrics](phase-4/stage-22) +- [Stage 22: Multiprocess](phase-4/stage-22) +- [Stage 23: Caching](phase-4/stage-23) +- [Stage 24: Transport Layer Security (TLS)](phase-4/stage-24) diff --git a/docs/roadmap/phase-1/stage-11.md b/docs/roadmap/phase-1/stage-11.md new file mode 100644 index 0000000..911e361 --- /dev/null +++ b/docs/roadmap/phase-1/stage-11.md @@ -0,0 +1 @@ +# Stage 11: Session Module diff --git a/docs/roadmap/phase-1/stage-6.md b/docs/roadmap/phase-1/stage-6.md index 8dde34d..e347f59 100644 --- a/docs/roadmap/phase-1/stage-6.md +++ b/docs/roadmap/phase-1/stage-6.md @@ -1,4 +1,4 @@ -# Stage 6: Server & Client Modules +# tage 6: Listener & Connection Modules ## Recap diff --git a/docs/roadmap/phase-1/stage-8.md b/docs/roadmap/phase-1/stage-8.md index fb35111..7559bfa 100644 --- a/docs/roadmap/phase-1/stage-8.md +++ b/docs/roadmap/phase-1/stage-8.md @@ -1 +1 @@ -# Stage 8: TCP Module +# Stage 8: Pipe Module diff --git a/docs/roadmap/phase-2/stage-11.md b/docs/roadmap/phase-2/stage-11.md deleted file mode 100644 index 51fbdfb..0000000 --- a/docs/roadmap/phase-2/stage-11.md +++ /dev/null @@ -1,184 +0,0 @@ -# Stage 11: HTTP Parser - -## Recap - -## Introduction - -You’ve made it to Phase 2! Till now, we only focused on TCP. But this phase will focus on HTTP connections. All the client requests and server responses will be HTTP messages. - -But what is HTTP you may ask. We have made a short and concise description for the same [here](https://www.notion.so/HTTP-e93e4b23676d4d5c9e939e7ae835237a?pvs=21). It is imperative that you have a clear understanding of the structure of HTTP messages as this stage will completely focus on writing a HTTP parser from the ground up! - -For eXpServer, we would only need to parse HTTP request messages. - -As eXpServer IS THE server, it would be the one to generate the HTTP response messages, not read them. But what about the cases when the server acts as a proxy? We will discuss about this in the next stage. - -Let us take an example HTTP request message and see how the parser will work. - -``` -GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages/httpmsg2.png HTTP/1.1 -Host: developer.mozilla.org -User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0 -Accept: image/avif,image/webp,*/* -Accept-Language: en-US,en;q=0.5 -Accept-Encoding: gzip, deflate, br -Referer: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages -``` - -We will split the parser into 2: - -1. Request line parser -2. Request headers parser - -To assist us with the parsing process, we will use `struct *xps_http_req_s`.\* - -### Request line parser - -The general structure of the an HTTP request line is the following: - -- Request method - GET -- Space -- Request URI - https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages/httpmsg2.png -- Space -- Request HTTP version - HTTP/1.1 - -The request URI can be of different types (refer the HTTP section). And each request URI has multiple subparts within it such as: - -- Schema - https -- Host - developer.mozilla.org -- Port - 443 (since its https, and a specific port is not mentioned in the URI) -- Path - /en-US/docs/Web/HTTP/Messages/httpmsg2.png -- Pathname - -The job of the parser is to take _any_ HTTP request message and be able to: - -1. Check if the HTTP request message is a valid -2. Split the message into different parts as mentioned above - -### Request headers parser - -The structure of a request header is the following: - -- Header key -- Semicolon -- Space -- Header value - -Similar to the request line parser, the request header parser should split each header into key-value pairs. We will store all the key-value pairs in a `vec_void_t headers`, which is part of `struct *xps_http_req_s`.\* - -## Implementation - -Like we mentioned before, we’ll split the HTTP request parser into two parts: - -1. `xps_http_parse_request_line` - to parse the request line -2. `xps_http_parse_header_line` - to parse the each header line - -```c -u_int xps_http_parse_request_line(xps_http_req_t *http_req, xps_buffer_t *buff) { - ... -} - -u_int xps_http_parse_header_line(xps_http_req_t *http_req, xps_buffer_t *buff) { - ... -} -``` - -`xps_buffer_t *buff` contains the HTTP request message that we need to parse. `xps_http_req_t *http_req` is an instance of the struct that we will use for parsing the message. - -If you look into `xps_http_req_t`, we can see that it mostly contains u_char\* pointers. The idea is simple: - -Iterate through the characters one by one. We are aware of the syntax of a standard HTTP request line. We use that to figure out where we are in the iteration step. - -Suppose we are parsing the request line, and the first character the first character. We know that this will be start of the request line, so we set a pointer there. - -```c -http_req->request_line_start = buff[0]; -``` - -We also know that the request line starts with the request method (GET, POST, PUT etc.). Therefore we can also set the request method start to the same position. - -```c -http_req->method_start = buff[0]; -``` - -We also know that the character HAS TO BE in the range(A to Z). We can use rules like these to validate and verify if the request message that we are receiving is of the correct format. - -> ::: tip -> Make use of parser_state (part of `http_req`) defined in `xps_http_parser.h` to keep track of where you are in the parsing process. -> ::: - -Here is some starting code that you can use to write the function. - -```c -#define LF (u_char)'\n' -#define CR (u_char)'\r' -#define CRLF "\r\n" - -u_int xps_http_parse_request_line(xps_http_req_t *http_req, xps_buffer_t *buff) { - u_char *p_ch; - u_int parser_state = http_req->parser_state; - - p_ch = buff->pos; - - for (u_int i = 0; i < buff->len; i++) { - if (i != 0) - p_ch += 1; - u_char ch = *p_ch; - - if (parser_state == RL_START) { - http_req->request_line_start = p_ch; - if (ch == CR || ch == LF) - continue; - if (ch < 'A' || ch > 'Z') - return XPS_HTTP_PARSE_INVALID_METHOD; - - http_req->method_start = p_ch; - parser_state = RL_METHOD; - continue; - } - - else if (parser_state == RL_METHOD) { - ... - } - - ... - - else if (parser_state == RL_LF) { - buff->pos = p_ch + 1; - if (http_req->request_line_end == NULL) - http_req->request_line_end = p_ch; - - http_req->parser_state = RL_START; - buff->pos = p_ch; - return OK; - } - } -} -``` - -You are not restricted to use the above mentioned approach. Coming up with your own type of implementation is well appreciated. - ---- - -### Milestone #1 - -Half way there! We can check if what we wrote can actually parse any HTTP request line. - ---- - -Similarly, we can now write the parser for the HTTP request header line. - -```c -u_int xps_http_parse_header_line(xps_http_req_t *http_req, xps_buffer_t *buff) { - ... -} -``` - -This should be smaller than the other function, and should take very less time. - ---- - -### Milestone #2 - -Let’s check this with some test cases. - -## Conclusion diff --git a/docs/roadmap/phase-2/stage-12.md b/docs/roadmap/phase-2/stage-12.md index ca166c5..377d9e4 100644 --- a/docs/roadmap/phase-2/stage-12.md +++ b/docs/roadmap/phase-2/stage-12.md @@ -1 +1,184 @@ -# Stage 12: HTTP Req & Res Modules +# Stage 12: HTTP Request Module + +## Recap + +## Introduction + +You’ve made it to Phase 2! Till now, we only focused on TCP. But this phase will focus on HTTP connections. All the client requests and server responses will be HTTP messages. + +But what is HTTP you may ask. We have made a short and concise description for the same [here](https://www.notion.so/HTTP-e93e4b23676d4d5c9e939e7ae835237a?pvs=21). It is imperative that you have a clear understanding of the structure of HTTP messages as this stage will completely focus on writing a HTTP parser from the ground up! + +For eXpServer, we would only need to parse HTTP request messages. + +As eXpServer IS THE server, it would be the one to generate the HTTP response messages, not read them. But what about the cases when the server acts as a proxy? We will discuss about this in the next stage. + +Let us take an example HTTP request message and see how the parser will work. + +``` +GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages/httpmsg2.png HTTP/1.1 +Host: developer.mozilla.org +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0 +Accept: image/avif,image/webp,*/* +Accept-Language: en-US,en;q=0.5 +Accept-Encoding: gzip, deflate, br +Referer: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages +``` + +We will split the parser into 2: + +1. Request line parser +2. Request headers parser + +To assist us with the parsing process, we will use `struct *xps_http_req_s`.\* + +### Request line parser + +The general structure of the an HTTP request line is the following: + +- Request method - GET +- Space +- Request URI - https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages/httpmsg2.png +- Space +- Request HTTP version - HTTP/1.1 + +The request URI can be of different types (refer the HTTP section). And each request URI has multiple subparts within it such as: + +- Schema - https +- Host - developer.mozilla.org +- Port - 443 (since its https, and a specific port is not mentioned in the URI) +- Path - /en-US/docs/Web/HTTP/Messages/httpmsg2.png +- Pathname + +The job of the parser is to take _any_ HTTP request message and be able to: + +1. Check if the HTTP request message is a valid +2. Split the message into different parts as mentioned above + +### Request headers parser + +The structure of a request header is the following: + +- Header key +- Semicolon +- Space +- Header value + +Similar to the request line parser, the request header parser should split each header into key-value pairs. We will store all the key-value pairs in a `vec_void_t headers`, which is part of `struct *xps_http_req_s`.\* + +## Implementation + +Like we mentioned before, we’ll split the HTTP request parser into two parts: + +1. `xps_http_parse_request_line` - to parse the request line +2. `xps_http_parse_header_line` - to parse the each header line + +```c +u_int xps_http_parse_request_line(xps_http_req_t *http_req, xps_buffer_t *buff) { + ... +} + +u_int xps_http_parse_header_line(xps_http_req_t *http_req, xps_buffer_t *buff) { + ... +} +``` + +`xps_buffer_t *buff` contains the HTTP request message that we need to parse. `xps_http_req_t *http_req` is an instance of the struct that we will use for parsing the message. + +If you look into `xps_http_req_t`, we can see that it mostly contains u_char\* pointers. The idea is simple: + +Iterate through the characters one by one. We are aware of the syntax of a standard HTTP request line. We use that to figure out where we are in the iteration step. + +Suppose we are parsing the request line, and the first character the first character. We know that this will be start of the request line, so we set a pointer there. + +```c +http_req->request_line_start = buff[0]; +``` + +We also know that the request line starts with the request method (GET, POST, PUT etc.). Therefore we can also set the request method start to the same position. + +```c +http_req->method_start = buff[0]; +``` + +We also know that the character HAS TO BE in the range(A to Z). We can use rules like these to validate and verify if the request message that we are receiving is of the correct format. + +> ::: tip +> Make use of parser_state (part of `http_req`) defined in `xps_http_parser.h` to keep track of where you are in the parsing process. +> ::: + +Here is some starting code that you can use to write the function. + +```c +#define LF (u_char)'\n' +#define CR (u_char)'\r' +#define CRLF "\r\n" + +u_int xps_http_parse_request_line(xps_http_req_t *http_req, xps_buffer_t *buff) { + u_char *p_ch; + u_int parser_state = http_req->parser_state; + + p_ch = buff->pos; + + for (u_int i = 0; i < buff->len; i++) { + if (i != 0) + p_ch += 1; + u_char ch = *p_ch; + + if (parser_state == RL_START) { + http_req->request_line_start = p_ch; + if (ch == CR || ch == LF) + continue; + if (ch < 'A' || ch > 'Z') + return XPS_HTTP_PARSE_INVALID_METHOD; + + http_req->method_start = p_ch; + parser_state = RL_METHOD; + continue; + } + + else if (parser_state == RL_METHOD) { + ... + } + + ... + + else if (parser_state == RL_LF) { + buff->pos = p_ch + 1; + if (http_req->request_line_end == NULL) + http_req->request_line_end = p_ch; + + http_req->parser_state = RL_START; + buff->pos = p_ch; + return OK; + } + } +} +``` + +You are not restricted to use the above mentioned approach. Coming up with your own type of implementation is well appreciated. + +--- + +### Milestone #1 + +Half way there! We can check if what we wrote can actually parse any HTTP request line. + +--- + +Similarly, we can now write the parser for the HTTP request header line. + +```c +u_int xps_http_parse_header_line(xps_http_req_t *http_req, xps_buffer_t *buff) { + ... +} +``` + +This should be smaller than the other function, and should take very less time. + +--- + +### Milestone #2 + +Let’s check this with some test cases. + +## Conclusion diff --git a/docs/roadmap/phase-2/stage-13.md b/docs/roadmap/phase-2/stage-13.md index a290cad..ea6adcf 100644 --- a/docs/roadmap/phase-2/stage-13.md +++ b/docs/roadmap/phase-2/stage-13.md @@ -1 +1 @@ -# Stage 13: Config & Session Modules +# Stage 13: HTTP Response Module diff --git a/docs/roadmap/phase-2/stage-14.md b/docs/roadmap/phase-2/stage-14.md index 35003e2..8a8f6f8 100644 --- a/docs/roadmap/phase-2/stage-14.md +++ b/docs/roadmap/phase-2/stage-14.md @@ -1 +1 @@ -# Stage 14: HTTP Specification +# Stage 14: Config Module diff --git a/docs/roadmap/phase-2/stage-15.md b/docs/roadmap/phase-2/stage-15.md new file mode 100644 index 0000000..a04e6ad --- /dev/null +++ b/docs/roadmap/phase-2/stage-15.md @@ -0,0 +1 @@ +# Stage 15: HTTP Specification diff --git a/docs/roadmap/phase-3/stage-15.md b/docs/roadmap/phase-3/stage-15.md deleted file mode 100644 index b8babb6..0000000 --- a/docs/roadmap/phase-3/stage-15.md +++ /dev/null @@ -1 +0,0 @@ -# Stage 15: IP Whitelist/Blacklist diff --git a/docs/roadmap/phase-3/stage-17.md b/docs/roadmap/phase-3/stage-17.md index 23f01c3..1150e47 100644 --- a/docs/roadmap/phase-3/stage-17.md +++ b/docs/roadmap/phase-3/stage-17.md @@ -1 +1 @@ -# Stage 17: Gzip Compression +# Stage 17: IP Whitelist/Blacklist diff --git a/docs/roadmap/phase-3/stage-18.md b/docs/roadmap/phase-3/stage-18.md index 091815c..9b141cb 100644 --- a/docs/roadmap/phase-3/stage-18.md +++ b/docs/roadmap/phase-3/stage-18.md @@ -1 +1 @@ -# Stage 18: Load Balancing +# Stage 18: Gzip Compression diff --git a/docs/roadmap/phase-3/stage-19.md b/docs/roadmap/phase-3/stage-19.md index 83ac1aa..1eae99b 100644 --- a/docs/roadmap/phase-3/stage-19.md +++ b/docs/roadmap/phase-3/stage-19.md @@ -1 +1 @@ -# Stage 19: Rate Limiting & Timeout +# Stage 19: Load Balancing diff --git a/docs/roadmap/phase-3/stage-20.md b/docs/roadmap/phase-3/stage-20.md new file mode 100644 index 0000000..28f0d35 --- /dev/null +++ b/docs/roadmap/phase-3/stage-20.md @@ -0,0 +1 @@ +# Stage 20: Request timeouts diff --git a/docs/roadmap/phase-4/stage-20.md b/docs/roadmap/phase-4/stage-20.md deleted file mode 100644 index 8c0db39..0000000 --- a/docs/roadmap/phase-4/stage-20.md +++ /dev/null @@ -1 +0,0 @@ -# Stage 20: Transport Layer Security (TLS) diff --git a/docs/roadmap/phase-4/stage-21.md b/docs/roadmap/phase-4/stage-21.md index 77fdc07..c4e6d20 100644 --- a/docs/roadmap/phase-4/stage-21.md +++ b/docs/roadmap/phase-4/stage-21.md @@ -1 +1 @@ -# Stage 21: Caching +# Stage 21: Metrics diff --git a/docs/roadmap/phase-4/stage-22.md b/docs/roadmap/phase-4/stage-22.md index 14a83e1..453930a 100644 --- a/docs/roadmap/phase-4/stage-22.md +++ b/docs/roadmap/phase-4/stage-22.md @@ -1 +1 @@ -# Stage 22: Multiprocess Architecture +# Stage 22: Multiprocess diff --git a/docs/roadmap/phase-4/stage-23.md b/docs/roadmap/phase-4/stage-23.md new file mode 100644 index 0000000..cf1cb38 --- /dev/null +++ b/docs/roadmap/phase-4/stage-23.md @@ -0,0 +1 @@ +# Stage 23: Caching diff --git a/docs/roadmap/phase-4/stage-24.md b/docs/roadmap/phase-4/stage-24.md new file mode 100644 index 0000000..6961c2e --- /dev/null +++ b/docs/roadmap/phase-4/stage-24.md @@ -0,0 +1 @@ +# Stage 24: Transport Layer Security (TLS) diff --git a/package.json b/package.json index ccea0d6..d005a23 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "homepage": "https://expserver.github.io", "scripts": { - "docs:dev": "vitepress dev docs", - "docs:build": "vitepress build docs", - "docs:preview": "vitepress preview docs" + "dev": "vitepress dev docs", + "build": "vitepress build docs", + "preview": "vitepress preview docs" }, "devDependencies": { "vitepress": "^1.0.0"