aboutsummaryrefslogtreecommitdiff
path: root/lib/http/server.go
AgeCommit message (Collapse)Author
2026-02-13lib/http: realign the fields in struct ServerShulhan
Previous struct size is 384 pointer bytes, now realign to 336 bytes (-48 bytes).
2026-02-11lib/http: implement server auto shutdown when idleShulhan
In the `ServerOptions`, we add option `ShutdownIdleDuration` when set to non-zero value it will start a timer. When the timer expired, the server will stop accepting new connection and then shutting down. This allow de-activating HTTP server when no connections received after specific duration to reduce the system resources.
2026-02-11lib/http: add BasePath to the ServerOptionsShulhan
The BasePath allow server to serve HTTP from custom prefix, other than "/". Each request that server received will remove the BasePath first from the [http.Request.URL.Path] before passing to the handler. Each redirect that server sent will add the BasePath as the prefix to redirect URL. Any trailing slash in the BasePath will be removed.
2026-02-05lib/http: change HandleFS redirect status code to 301 Moved PermanentlyShulhan
According to MDN [Redirections in HTTP], the HTTP status 302 Found use case is The Web page is temporarily unavailable for unforeseen reasons. This probably to re-route the page until the original page is fixed. While HTTP status 301 is for Reorganization of a website. Since the redirection in HandleFS only happen when user access directory without slash, we should make it permanent. [Redirections in HTTP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections
2026-02-05lib/http: handle file system with canonical directory end with slash "/"Shulhan
Previously, if request to directory does not end with "/", the HTTP server will return the index.html of that directory. This cause relative link inside the index.html broken when visited from browser. This changes make the request to directory always end with "/" by redirecting the request with status 303 Found.
2026-02-02lib/http: add field Listener to ServerOptionsShulhan
The field Listener allow user to pass [net.Listener] for accepting new connection using [http.Serve] or [http.ServeTLS].
2026-01-06lib/http: add second return value, statusCode, to FSHandlerShulhan
Non-zero status code indicates that the function already response to the request, and the server will return immediately. Zero status code indicates that the function did not process the request, it is up to server to process the returned node `out`.
2025-01-22lib/http: always refresh a directory on GET requestShulhan
On server with TryDirect is true, any GET request to a directory should always rescan the content and the generate the new index.html. While at it, return the generated time in UTC instead of local time.
2024-09-30lib/http: add Server method to register handler by functionShulhan
The RegisterHandleFunc register a pattern with a handler, similar to [http.ServeMux.HandleFunc]. The pattern follow the Go 1.22 format: [METHOD] PATH The METHOD is optional, default to GET. The PATH must not contains the domain name and space. Unlike standard library, variable in PATH is read using ":var" not "{var}". This endpoint will accept any content type and return the body as is; it is up to the handler to read and set the content type and the response headers. If the METHOD and/or PATH is already registered it will panic.
2024-03-26lib/http: remove unnecessary second return value in getFSNodeShulhan
The second return valus is a boolean to indicate that node is directory, which can also retrieved from Node using method IsDir.
2024-03-21lib/memfs: trim trailing slash ("/") in the path of Get methodShulhan
The MemFS always store directory without slash. If caller request a directory node with slash, it will always return nil.
2024-03-15lib/http: refactoring FSHandler type to return [*memfs.Node]Shulhan
Changing FSHandler type to return [*memfs.Node], allow the handler to redirect or return custom node. One of the use case is when service Single Page Application (SPA), where route is handled by JavaScript. For example, when user requested "/dashboard" but dashboard directory does not exist, one can write the following handler to return "/index.html", { node, _ = memfs.Get(`/index.html`) return node }
2024-03-15lib/http: refactoring type of RequestMethod from int to stringShulhan
The reason is to make storing or encoding the RequestMethod value readable from user point of view instead of number, 0, 1, 2, etc.
2024-03-09lib/http: refactoring NewServer and NewClientShulhan
The NewServer and NewClient now accept non-pointer options, so the caller unable to modify the options once the server or client has been created.
2024-03-09lib/http: refactor of RegisterEndpoint and RegisterSSE to non-pointerShulhan
Once the endpoint registered, the caller should not able to changes any values on endpoint again.
2024-03-05lib/http: move CORS initialization and handler to cors_optionsShulhan
This is to decoupling between ServerOptions and Server handlers.
2024-03-05lib/http: handle CORS independentlyShulhan
Previously, if [CORSOptions.AllowOrigins] not found we return it immediately without checking request "Access-Control-Request-Method", "Access-Control-Request-Headers", and other CORS options. This changes check each of them, a missing allow origins does not means empty allowed method, headers, MaxAge, or credentials.
2024-03-05all: comply with linter recommendations #3Shulhan
For HTTP server that use TLS, set the minimum TLS version and ReadHeaderTimeout to mitigate slowloris attack. For HTTP client or server that parameterize the use of InsecureSkipVerify, annotate the line with "nolint:gosec" to allow the code pass the check. Library that still use sha1, in example in DKIM and TOTP, skip the warnings by annotating the line with "nolint:gosec". A pointer variable now allocated their address before assigning its value. Any error that returned now wrapped using "%w". Also, replace error checking using [errors.Is] or [errors.As] instead of using equal or not-equal operators. In "lib/http", replace any usage of "math/rand" with "crypto/rand". Any call of [math/big.Rat.SetString] now annotated with "nolint:gosec" since its false positive, the issue has been fixed in Go >= 1.17.7. Any switch case that does not cover the rest of the possible values now handled by adding the cases or by replacing the "default" case with the rest of values.
2024-03-05all: comply with linter recommendations #2Shulhan
HTTP request now implicitly create request with context. Any false positive related to not closing HTTP response body has been annotated with "nolint:bodyclose". In the example code, use consistent "// Output:" comment format, by prefixing with single space. Any comment on code now also prefixing with single space. An error returned without variables now use [errors.New] instead of [fmt.Errorf]. Any error returned using [fmt.Errorf] now wrapped using "%w" instead of "%s". Also, replace error checking using [errors.Is] or [errors.As], instead of using equal/not-equal operator. Any statement like "x = x OP y" now replaced with "x OP= y". Also, swap statement is simplified using "x, y = y, x". Any switch statement with single case now replaced with if-condition. Any call to defer on function or program that call [os.Exit], now replaced by calling the deferred function directly. Any if-else condition now replaced with switch statement, if possible.
2024-03-05all: comply with linter recommendations #1Shulhan
Instead of annotating the lines that caught by linters, fix it to comply with the recommendations. This causes several breaking changes, especially related to naming, * api/slack: [Message.IconUrl] become [Message.IconURL] * lib/dns: DefaultSoaMinumumTtl become DefaultSoaMinimumTTL * lib/email: [Message.SetBodyHtml] become [Message.SetBodyHTML] * lib/http: [Client.GenerateHttpRequest] become [Client.GenerateHTTPRequest] * lib/http: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] * lib/http: [EndpointRequest.HttpWriter] become [EndpointRequest.HTTPWriter] * lib/http: [EndpointRequest.HttpRequest] become [EndpointRequest.HTTPRequest] * lib/http: [ServerOptions.EnableIndexHtml] become [ServerOptions.EnableIndexHTML] * lib/http: [SSEConn.HttpRequest] become [SSEConn.HTTPRequest] * lib/smtp: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] * lib/ssh/sftp: [FileAttrs.SetUid] become [FileAttrs.SetUID] * lib/ssh/sftp: [FileAttrs.Uid] become [FileAttrs.UID]
2024-03-02all: move the repository to "git.sr.ht/~shulhan/pakakeh.go"Shulhan
There are several reasons that why we move from github.com. First, related to the name of package. We accidentally name the package with "share" a common word in English that does not reflect the content of repository. By moving to other repository, we can rename it to better and unique name, in this "pakakeh.go". Pakakeh is Minang word for tools, and ".go" suffix indicate that the repository related to Go programming language. Second, supporting open source. The new repository is hosted under sourcehut.org, the founder is known to support open source, and all their services are licensed under AGPL, unlike GitHub that are closed sources. Third, regarding GitHub CoPilot. The GitHub Terms of Service [1], allow any public content that are hosted there granted them to parse the content. On one side, GitHub helps and flourish the open source, but on another side have an issues regarding scraping the copyleft license [2]. [1]: https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#4-license-grant-to-us [2]: https://githubcopilotinvestigation.com
2024-01-25lib/path: new package to work with pathShulhan
The path package provide a new type Route, detached from "lib/http". A Route represent a parsed path. A path can have a key, or binding, that can be replaced with string value. For example, "/org/:user/:repo" have two keys "user" and "repo". Route handle the path in case-insensitive manner.
2024-01-24lib/http: add support for If-Modified-Since in HandleFSShulhan
If the node modification time is less than requested time value in request header If-Modified-Since, server will response with 304 Not Modified.
2024-01-24lib/http: update doc to use comment linksShulhan
2024-01-24lib/http: refactoring Range request, limit content served by serverShulhan
When server receive, GET /big Range: bytes=0- and the requested resources is quite larger, where writing all content of file result in i/o timeout, it is best practice [1][2] if the server write only partial content and let the client continue with the subsequent Range request. In the above case, the server should response with, HTTP/1.1 206 Partial content Content-Range: bytes 0-<limit>/<size> Content-Length: <limit> Where limit is maximum packet that is reasonable [3] for most of the client. In this server we choose 8MB as limit. [1]: https://stackoverflow.com/questions/63614008/how-best-to-respond-to-an-open-http-range-request [2]: https://bugzilla.mozilla.org/show_bug.cgi?id=570755 [3]: https://docs.aws.amazon.com/whitepapers/latest/s3-optimizing-performance-best-practices/use-byte-range-fetches.html
2023-12-13all: fix linter warnings reported by reviveShulhan
There are some reports that I disagree with revive, in example, code should not declare the type after variables. In my opinion, on some cases, declaring the type make the code more readable and explicit. Since I did not want to add new configuration file, we changes it and follow revive for now.
2023-11-26lib/http: implement Server-Sent Events (SSE)Shulhan
For server SSE, we add new type SSEEndpoint, for registering endpoint that can handle SSE. For client SSE, we add it in new sub package "sseclient". Implements: https://todo.sr.ht/~shulhan/share/1 Implements: https://todo.sr.ht/~shulhan/share/2 Signed-off-by: Shulhan <ms@kilabit.info>
2023-07-09lib/http: fix missing query when handling redirect in HandleFSShulhan
In 06e6cbdd511c, we redirect request by adding end slash to the path if the requested resource is directory, but somehow we miss adding the original request query. This changes fix this issue.
2023-05-25lib/http: redirect path with slash if request is directoryShulhan
If request path is a directory and it is not end with slash, redirect request to location with slash to allow relative links works inside the HTML content. For example, a "/page/index.html" contains links href="sub.html" (where "sub.html" is inside "/page" directory). If request to "/page" (without end with slash) return content of "/page/index.html", then when user click on sub.html it will request to "/sub.html" instead of "/page/sub.html".
2023-05-20all: remove any usage of debug.Value in all packagesShulhan
Using global debug value for all packages turns out is not a good idea.
2023-03-26lib/http: check and log the error when writing response in handleRangeShulhan
We use the mlog, so user that also use mlog can record the error.
2023-03-12lib/http: reformat comment in Client GenerateHttpRequestShulhan
While at it, add comment for function generateFormData and Server method handleHead.
2023-03-12lib/http: add support for HTTP Range in ServerShulhan
For HTTP Server using HandleFS, the Range request is handled automatically. For other HTTP server, user can use the HandleRange function. The HandleRange function handle [HTTP Range] request using "bytes" unit. The body parameter contains the content of resource being requested that accept Seek method. If the Request method is not GET, or no Range in header request it will return all the body [RFC7233 S-3.1]. The contentType is optional, if its empty, it will detected by http.ResponseWriter during Write. [HTTP Range]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests [RFC7233 S-3.1]: https://datatracker.ietf.org/doc/html/rfc7233#section-3.1 # Conflicts: # CHANGELOG.adoc
2023-02-25all: access embedded field or methods using the type nameShulhan
This is for clarity in the code, better to be explicit by typing where the field or methods come from.
2022-08-03lib/http: add server options to generate index.html automaticallyShulhan
If the EnableIndexHtml in the ServeOptions enabled, server generate list of files inside the requested path as HTML.
2022-05-09all: reformat all codes using gofmt 1.19 (the Go tip)Shulhan
2022-04-06all: replace any usage of ioutil package with os or ioShulhan
Since Go 1.16, the ioutil package has been deprecated. This changes replace any usage that use functions from ioutil package with their replacement from package os or package io.
2022-03-31lib/http: rewrite ServerOptions FSHandler to handle request in generalShulhan
This changes rename ServerOptions field FSAuthHandler to FSHandler and rewrite their usage. The FSHandler define the function to inspect each GET request to Server MemFS instance. The node parameter contains the requested file inside the memfs. If the handler return true, server will continue processing the node (writing the Node content type, body, and so on). If the handler return false, server stop processing the node and return immediately, which means the function should have already handle writing the header, status code, and/or body.
2022-03-30lib/http: implement handler to authorized request to Server MemfsShulhan
The FSAuthHandler in the ServerOptions define a function that will be called to each GET request to Server Memfs instance using the value from the HTTP Request instance. If the request is not authorized it must return false and the HTTP response will be set to 401 Unauthorized with empty body.
2022-03-27lib/http: use package mlog for loggingShulhan
In case the consumer of lib/http package use mlog for logging, the log will be written to their predefined writers. In case they did not use mlog, the log will written to stdout and stderr.
2021-12-26lib/http: remove field memfs.Options in ServerOptionsShulhan
This options is duplicate with Memfs.Opts.
2021-12-19lib/memfs: remove field ContentEncoding from EmbedOptions and NodeShulhan
The original idea for option ContentEncoding in EmbedOptions and Node is to save spaces, compressing the content on disk on embedding and doing transport, when the MemFS instance is used to serve the (embedded) contents of file system. This option turns out break the HTTP content negotiation [1] of accept-encoding header, if the HTTP server does not handle it properly, which default Go HTTP server does not. In order to prevent this issue in the future, for anyone who use the memfs for serving static HTTP contents, we remove the options and store the embedded content as is and let the HTTP server handle how the compression by itself. [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation
2021-10-09lib/memfs: refactoring Node field V into ContentShulhan
The reason why the field named V is because it's short. It's come from my C/C++ experience that got carried away when writing this package. Now, after having more time writing Go, I prefer clarity over cleverity(?).
2021-09-22lib/http: support server caching file system using ETagShulhan
If the Server handle file system using MemFS, server will set the ETag [1] header using the file epoch as value. On the next request, server will compare the request header If-None-Match with the requested file epoch. If its equal server will return the response as 304 StatusNotModified. [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
2021-08-17lib/http: fix missing content type for XML HeaderShulhan
If the Endpoint set the RequestType to RequestTypeXML, the response header should be set to ContentTypeXML.
2021-08-06lib/http: fix return value on getFSNodeShulhan
On c8dd20254d, we check the request path by adding .html suffix but forgot to return node if its not nil.
2021-07-08lib/http: check request path as HTML file on getFSNodeShulhan
Previously, if the request path is not exist we check if request contains index.html and if still not exist we return nil. This commit add another check by appending ".html" to the request path. So, for example, if path "/x" not exist in memfs, we check if "/x/index.html". If its still not exist, we check "/x.html".
2021-06-26http: remove the Memfs field from ServerShulhan
Now that Options field has been exported, we did not need to have duplicate Memfs, so this field is removed in favor of Options.Memfs.
2021-06-26http: export the Options field on the ServerShulhan
Previously, the Options field is not exported to prevent user from changing it once it set throught NewServer() function. This changes export the Options field to allow user of Server access its values. We can create a method on server to return read-only options, but that will over complicated the Server API.
2021-03-05http: move the CORS options in ServerOptions to separate structShulhan
The CORS options are optional and rarely used, its usually handled by proxy. So, we move them to separate struct to make the actual server options short.