
Golang's http package is a powerful tool for building web applications. It provides a simple and efficient way to handle HTTP requests and responses.
The http package in Golang is built on top of the net package, which provides a low-level interface for networking. This allows developers to create highly performant and scalable web servers.
To create an HTTP server in Golang, you can use the `http.ListenAndServe()` function, which takes two arguments: the address to listen on and a handler function. The handler function is responsible for handling incoming requests.
A good example of a simple HTTP handler is the `http.HandlerFunc` type, which takes a function that takes an `http.ResponseWriter` and an `http.Request` as arguments.
For another approach, see: Create a Package in Golang
HTTP Basics
The Go package http provides HTTP client and server implementations, allowing you to make HTTP (or HTTPS) requests using functions like Get, Head, Post, and PostForm.
To make a request, you must close the response body when finished with it. This is a crucial step to avoid resource leaks.
In Go, HTTP status codes have a corresponding text representation that can be retrieved using the StatusText function. If the code is unknown, it returns an empty string.
Expand your knowledge: Golang Go
Overview
The http package in Go provides HTTP client and server implementations. It includes functions like Get, Head, Post, and PostForm to make HTTP requests. The caller must close the response body when finished with it.
The http package also includes a ServeMux, which is a multiplexor for handling multiple HTTP requests. It's used to match incoming requests against a list of registered routes. The ServeMux is an http.Handler, which means it has a ServeHTTP method.
You can create a simple HTTP server using the http.HandleFunc function. This function adds a handler to a http.DefaultServerMux object, which is a predefined object. The handler function takes a http.ResponseWriter and a http.Request object.
To serve static files, you can use the http package to serve files directly from your HTTP server. This is useful for web applications that require delivering static assets to clients.
Status Text
The StatusText function returns a text for the HTTP status code. It's a helpful tool for understanding what's happening behind the scenes.
If the HTTP status code is unknown, StatusText returns an empty string. This can be useful for debugging purposes.
StatusText is a straightforward function that provides a clear message for each status code.
Explore further: Golang Http Status Code
Compatibility
The compatibility of ServeMux has undergone significant changes in Go 1.22. To restore the old behavior, set the GODEBUG environment variable to "httpmuxgo121=1".
This setting is read once, at program startup, and changes during execution will be ignored.
The backwards-incompatible changes include changes to pattern syntax and matching behavior.
This change affects how ServeMux handles HTTP requests.
Request and Response
The `net/http` package in Go enables us to access and process information from incoming HTTP requests, such as headers and the data sent in the request body. This allows us to handle requests and responses in a structured way.
We can construct and send HTTP requests to other servers, including setting headers, providing data in the request body, and processing the responses received. This is done using the `http` package, which provides a flexible way to interact with external HTTP APIs.
A handler function is used to respond to incoming HTTP requests, and it can accept two arguments: `ResponseWriter` and `Request`. The `ResponseWriter` interface aids in sending data back to the client as a response, while the `Request` is a structured data containing details about the incoming request.
You might like: Golang Make Http Request
Get (*)
The `Get` function in the `net/http` package is a powerful tool for retrieving data from external services. It issues a GET request to the specified URL and follows redirects if the response code is in the 3xx range.
You can use `Get` to follow redirects after calling the `CheckRedirect` function. An error is returned if the `CheckRedirect` function fails or if there was an HTTP protocol error.
When making a request with custom headers, use `NewRequest` and `Client.Do` instead of `Get`. Similarly, to make a request with a specified `context.Context`, use `NewRequestWithContext` and `Client.Do`.
The `Get` function always returns a non-nil `resp.Body` when `err` is nil. You should close `resp.Body` when you're done reading from it to avoid memory leaks.
If you're working with external services, `Get` can be a great way to retrieve data and integrate it into your application. Just be sure to follow the right steps to handle redirects and errors.
Worth a look: Docker Client Golang
Read
Reading HTTP requests and responses is a crucial part of working with the net/http package. You can read and parse an incoming request from a buffer using the ReadRequest function, which is a low-level function that should only be used for specialized applications.
The ReadRequest function only supports HTTP/1.x requests, while HTTP/2 requests should be handled using the golang.org/x/net/http2 package. This function reads and parses the entire request, including headers and body.
To read the response body, you can use the Body field of the Response object, which is a ReadCloser that streams the response body on demand as it is read. It's essential to close the Body field when finished reading to avoid resource leaks.
Here are some key facts to keep in mind when reading HTTP requests and responses:
- ReadRequest is a low-level function for parsing incoming requests.
- ReadRequest only supports HTTP/1.x requests.
- Use golang.org/x/net/http2 for HTTP/2 requests.
- Close the Body field when finished reading to avoid resource leaks.
The Response object also provides methods for reading and writing HTTP responses. For example, you can use the Cookies method to parse and return the cookies set in the Set-Cookie headers. Similarly, you can use the Write method to write an HTTP/1.1 request or response in wire format.
Recommended read: Golang Use Cases
When reading the response body, it's essential to handle errors and edge cases, such as when the response body is too large to fit in memory. The MaxBytesReader function can be used to limit the size of incoming request bodies and prevent clients from sending large requests that waste server resources.
In addition, the ResponseController object provides methods for controlling the response, such as setting deadlines for reading and writing the response. For example, you can use the SetReadDeadline method to set a deadline for reading the entire request, including the body.
By understanding how to read and parse HTTP requests and responses, you can build more robust and efficient HTTP clients and servers using the net/http package.
FS in 1.22.0
FS in 1.22.0 is a significant addition to Go's net/http package. It allows you to serve files from a file system.
The FS function converts a file system to a FileSystem implementation, which is used with FileServer and NewFileTransport. The files provided by fsys must implement io.Seeker.

ServeFileFS is a function that serves the contents of a named file or directory from the file system fsys. It's a good practice to sanitize the name before calling ServeFileFS.
NewFileTransportFS returns a new RoundTripper that serves the provided file system fsys. The files provided by fsys must implement io.Seeker.
FileServerFS returns a handler that serves HTTP requests with the contents of the file system fsys. The files provided by fsys must implement io.Seeker.
ServeFileFS has some special cases to protect against potential security issues. It rejects requests where r.URL.Path contains a ".." path element and redirects requests where r.URL.Path ends in "/index.html" to the same path without the final "index.html".
Intriguing read: Golang Html
WriteSubset
The WriteSubset function is used to write a header in wire format. It's a useful tool for controlling what gets written to the header.
If you want to exclude certain keys from being written, you can pass in a map with the keys you want to exclude. This is done by setting the exclude map with keys where the value is true.
Keys are not canonicalized before checking the exclude map, so you need to make sure the keys are spelled correctly.
This function is part of the Header type, which is used to write HTTP headers. It's a simple but powerful tool for controlling the output of your HTTP requests.
Take a look at this: S Golang
Literals and Closures
Function literals provide a powerful means of abstracting functionality, allowing us to wrap each handler in a function that does validation and error checking.
Catching the error condition in each handler introduces a lot of repeated code, but with function literals, we can create a wrapper function that takes a function of a certain type and returns a function of another type.
This wrapper function is called a closure because it encloses values defined outside of it, in this case, the variable fn, which is one of the save, edit, or view handlers.
The closure returned by makeHandler is a function that takes an http.ResponseWriter and http.Request, making it suitable to be passed to the http.HandleFunc function.
The enclosed handler function fn will be called with the ResponseWriter, Request, and title as arguments if the title is valid, otherwise an error will be written to the ResponseWriter using the http.NotFound function.
By using makeHandler to wrap the handler functions, we can remove the calls to getTitle from the handler functions, making them much simpler.
Request and Response (continued)
A ResponseWriter interface is used by an HTTP handler to construct an HTTP response. This interface helps in sending data back to the client as a response.
The Client and Transport return Responses from servers once the response headers have been received. The response body is streamed on demand as the Body field is read.
A ResponseController is used by an HTTP handler to control the response. However, it may not be used after the Handler.ServeHTTP method has returned.
Unencrypted 2
Unencrypted 2 is a feature that's made its way into the Protocols in Go 1.24.0. This feature allows you to add or remove unencrypted HTTP/2 from the Protocols.
SetUnencryptedHTTP2 is the function that's responsible for adding or removing unencrypted HTTP/2. It's a simple and straightforward way to manage this feature.
UnencryptedHTTP2 reports whether the Protocols include unencrypted HTTP/2. This is a useful function to have, especially when you need to check if a certain protocol is enabled.
You can use SetUnencryptedHTTP2 to add unencrypted HTTP/2 to the Protocols. This can be a useful feature in certain scenarios.
The UnencryptedHTTP2 function returns a boolean value indicating whether unencrypted HTTP/2 is included in the Protocols. This makes it easy to check the status of this feature.
Template Caching

Template caching is a game-changer for efficiency. By calling ParseFiles once at program initialization, we can parse all templates into a single *Template, which we can then use to render specific templates with the ExecuteTemplate method. This approach eliminates the need to call ParseFiles every time a page is rendered.
The function template.Must is a helpful wrapper that panics when passed a non-nil error value, and otherwise returns the *Template unaltered. This is a good thing, because if the templates can't be loaded, the only sensible thing to do is exit the program.
To implement template caching, we create a global variable named templates and initialize it with ParseFiles. This allows us to reuse the parsed templates for future requests.
Example 3:
In Example 3, we create an HTTP client using the http.Client type. This type of client is useful for making GET requests to specific URLs.
The client makes a GET request to the "https://api.example.com/data" URL. The response body is then read and printed to the console, allowing us to see the data received from the server.

To manually configure HTTP/2 via the golang.org/x/net/http2 package, you need to import the package directly and use its ConfigureTransport and/or ConfigureServer functions. This takes precedence over the net/http package's built-in HTTP/2 support.
The http.Client type can be used to make GET requests to specific URLs, and the response body can be read and printed to the console. However, for more complex configurations, you may need to manually configure HTTP/2.
Here's a list of the http package's Transport and Server functions that automatically enable HTTP/2 support for simple configurations:
- FileServer
- FileServer (DotFileHiding)
- FileServer (StripPrefix)
- Get
- Handle
- HandleFunc
- Hijacker
- ListenAndServe
- ListenAndServeTLS
- NotFoundHandler
- Protocols (Http1)
- Protocols (Http1or2)
- ResponseWriter (Trailers)
- ServeMux.Handle
- Server.Shutdown
- StripPrefix
Request and Response (continued)
A ResponseController is used by an HTTP handler to control the response, but it may not be used after the Handler.ServeHTTP method has returned.
The Client and Transport return Responses from servers once the response headers have been received, and the response body is streamed on demand as the Body field is read.
A ResponseWriter interface is used by an HTTP handler to construct an HTTP response, and it may not be used after Handler.ServeHTTP has returned.
Consider reading: Golang Body
You can construct and send HTTP requests to other servers using the package, including setting headers, providing data in the request body, and processing the responses received.
The provided code defines an HTTP handler function for the ‘/users’ route using the ‘http’ package, which responds to incoming HTTP requests on that route, processing them according to the specific request method.
In case the method is anything other than GET or POST, the handler will respond by sending an ‘Invalid request method’ message back to the client using the http.Error function, along with a StatusMethodNotAllowed HTTP status code.
A ResponseController has a Flush method that flushes buffered data to the client.
Cookies and Authentication
Cookies play a crucial role in authentication in the world of HTTP. You can set cookies in the response headers using the Response object's Cookies function, which parses and returns the cookies set in the Set-Cookie headers.
The Cookies function is especially useful for setting authentication cookies, which can be used to identify users and track their sessions. You can also use the Cookies function to set cookies for other purposes, such as storing user preferences.
To read cookies from a request, you can use the Request object's Cookies function, which parses and returns the HTTP cookies sent with the request. The Cookies function returns a list of Cookie objects, which you can then use to access the cookie values and attributes.
Cookies
Cookies are an essential part of HTTP requests and responses, allowing servers to store and retrieve data from clients. They can be set in the response headers using the SetCookie function, which adds a Set-Cookie header to the provided ResponseWriter's headers.
Invalid cookies may be silently dropped if they don't have a valid Name. This is a key consideration when working with cookies in Go. A CookieJar is a type that manages storage and use of cookies in HTTP requests, and the net/http/cookiejar package provides an implementation of a CookieJar.
The Cookie type has a Valid method that reports whether the cookie is valid. If multiple cookies match a given name, only one cookie will be returned when using the Cookie function. This is because the Cookie function returns the named cookie provided in the request or ErrNoCookie if not found.
Cookies can be added to a request using the AddCookie function, which sanitizes the cookie's name and value. However, it does not sanitize a Cookie header already present in the request. This means that if a Cookie header is already present, the new cookie will be appended to it, separated by a semicolon.
The Cookies function can be used to parse and return the HTTP cookies sent with the request. This function can return multiple cookies for the same name, which can be useful in certain scenarios. The ParseCookie function is similar, but it parses a Cookie header value and returns all the cookies which were set in it.
Add Insecure Bypass to CORS Protection in 1.25.0
In Go 1.25.0, a new feature was added to CrossOriginProtection called AddInsecureBypassPattern. This method permits all requests that match the given pattern.
The pattern syntax and precedence rules are the same as ServeMux, which can be a bit tricky to understand at first. However, with practice, you'll get the hang of it.
AddInsecureBypassPattern can be called concurrently with other methods or request handling, and applies to future requests. This means you can use it in production without worrying about performance issues.
You can use AddInsecureBypassPattern to allow certain requests to bypass cross-origin checks, even if they don't meet the usual security requirements. Just be sure to use it judiciously, as it can weaken your security posture if not used carefully.
In theory, you could use AddInsecureBypassPattern to allow requests from a specific domain or IP address, but you'd need to know the exact pattern syntax and rules to get it working correctly.
Basic Auth
Basic Auth is a type of HTTP authentication that uses a username and password to verify a user's identity.
The BasicAuth function returns the username and password provided in the request's Authorization header, if the request uses HTTP Basic Authentication. This is specified in RFC 2617, Section 2.
To use Basic Auth, the request must be made over HTTPS, as the username and password are not encrypted.
The username may not contain a colon, and some protocols may require pre-escaping the username and password, such as when used with OAuth2, where both arguments must be URL encoded first with url.QueryEscape.
Setting the Authorization header to use HTTP Basic Authentication with a specific username and password can be done using the SetBasicAuth function.
Cookies and Authentication
Cookies play a crucial role in HTTP authentication, allowing servers to store and retrieve data about users. The golang http package provides functions to work with HTTP cookies.
You can set cookies in the response headers using the Cookies function of the Response object, which parses and returns the cookies set in the Set-Cookie headers. This is useful for storing user authentication data.
Intriguing read: Golang Authentication
The Valid function of the Cookie object reports whether the cookie is valid, allowing you to check if a cookie has been set correctly. This is an important step in the authentication process.
To read cookies from the request, you can use the Cookies function of the Request object, which parses and returns the HTTP cookies sent with the request. This data can be used to authenticate users.
The ParseSetCookie function parses a Set-Cookie header value and returns a cookie, which can be used to set cookies in the response headers. This function returns an error on syntax error, so it's essential to handle errors properly.
Cookies and Authentication
Cookies play a crucial role in authentication, allowing servers to verify user identities and grant access to protected resources.
The `ParseSetCookie` function can be used to parse a Set-Cookie header value and return a cookie, which helps to establish a user's identity.
To check if a cookie is valid, you can use the `Valid` method on a `*Cookie` object.
The `Cookies` method on a `*Request` object parses and returns the HTTP cookies sent with the request, providing valuable information about the user's identity.
The `Cookies` method on a `*Response` object parses and returns the cookies set in the Set-Cookie headers, allowing you to manage and manipulate cookie values.
By leveraging these functions and types, you can effectively work with HTTP cookies and implement robust authentication mechanisms in your Go applications.
Headers and Protocols
Headers are a crucial part of HTTP communication, and in Go, they're represented by the Header type. A Header represents the key-value pairs in an HTTP header, and the keys should be in canonical form.
The Header type has two main methods: Set and Get. Set sets the header entries associated with a key to a single element value, replacing any existing values, while Get gets the first value associated with a given key, returning an empty string if no values are associated with the key.
You might like: Golang Type
To use non-canonical keys, you can assign to the map directly, but it's recommended to use the CanonicalMIMEHeaderKey function to canonicalize the key. This is because Get assumes all keys are stored in canonical form.
Here's a quick reference on how to use the Header type:
In addition to headers, understanding protocols is also essential in Go's HTTP package. The Protocols type represents the supported protocols, which include HTTP1, HTTP2, and UnencryptedHTTP2.
Content
Content is a crucial aspect of HTTP communication, and the Go HTTP package provides several functions to handle content-related tasks. The DetectContentType function implements the algorithm described at https://mimesniff.spec.whatwg.org/ to determine the Content-Type of the given data.
DetectContentType considers at most the first 512 bytes of data and always returns a valid MIME type. If it cannot determine a more specific one, it returns "application/octet-stream".
The ServeContent function replies to the request using the content in the provided ReadSeeker. It handles Range requests properly, sets the MIME type, and handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, and If-Range requests.
ServeContent first tries to deduce the type from name's file extension and, if that fails, falls back to reading the first block of the content and passing it to DetectContentType.
If the response's Content-Type header is not set, ServeContent includes it in the response. If the request includes an If-Modified-Since header, ServeContent uses modtime to decide whether the content needs to be sent at all.
The content's Seek method must work: ServeContent uses a seek to the end of the content to determine its size. If the caller has set w's ETag header formatted per RFC 7232, section 2.3, ServeContent uses it to handle requests using If-Match, If-None-Match, or If-Range.
If an error occurs when serving the request, ServeContent responds with an error message. By default, ServeContent strips the Cache-Control, Content-Encoding, ETag, and Last-Modified headers from error responses.
ParseVersion
Parsing HTTP versions is a crucial step in understanding how HTTP requests are structured. The `ParseHTTPVersion` function takes an HTTP version string and returns a tuple of three values: the major version, the minor version, and a boolean indicating whether the minor version is present.
According to RFC 7230, section 2.6, the `ParseHTTPVersion` function returns (1, 0, true) for the string "HTTP/1.0". This is because the string specifies a minor version, which is a valid HTTP version.
Strings without a minor version, like "HTTP/2", are not valid HTTP versions. This is because they don't conform to the rules outlined in RFC 7230.
The `ParseHTTPVersion` function is a key component in ensuring that HTTP requests are properly formatted and understood by servers and clients.
Parse Time 1.1
In HTTP/1.1, the ParseTime function is a crucial tool for parsing time headers.
The ParseTime function tries each of the three formats allowed by HTTP/1.1: TimeFormat, time.RFC850, and time.ANSIC. It's a flexible approach that ensures accurate time parsing.
The TimeFormat is one of the allowed formats that ParseTime tries. It's a specific format that HTTP/1.1 expects for time headers.
The time.RFC850 and time.ANSIC formats are the other two formats that ParseTime attempts to parse. These formats are also specified by HTTP/1.1 as valid time header formats.
The ParseTime function is a useful tool for developers working with HTTP/1.1 protocols. It helps ensure that time headers are parsed correctly and consistently.
Fs In 1.22.0

Fs In 1.22.0 was a significant update that brought several improvements to the way we handle file systems.
The ServeFileFS function was added in 1.22.0 and allows us to reply to requests with the contents of a named file or directory from the file system fsys.
As a precaution, ServeFileFS will reject requests with ".." path elements in r.URL.Path to protect against potential security vulnerabilities.
ServeFileFS also has a special case where it redirects requests ending in "/index.html" to the same path without the final "index.html".
The FS function, added in 1.16, converts fsys to a FileSystem implementation for use with FileServer and NewFileTransport.
FileServerFS, added in 1.22.0, returns a handler that serves HTTP requests with the contents of the file system fsys.
NewFileTransportFS, also added in 1.22.0, returns a new RoundTripper that serves the provided file system fsys, ignoring the URL host in its incoming requests.
The files provided by fsys must implement io.Seeker in all these functions to ensure they can be served correctly.
Head
The Head method is a powerful tool for making requests to a server without retrieving the actual content. It issues a HEAD request to the specified URL.
If the response is a redirect, the Head method will follow it, but only after checking the redirect policy using the Client.CheckRedirect function. This allows you to control how the method handles redirects.
Head is also a wrapper around the DefaultClient.Head method, which means it uses the same underlying logic to follow redirects, up to a maximum of 10 redirects. This ensures consistency and reliability in your requests.
Add Trusted Origin to CORS Protection
Adding a trusted origin to your Cross-Origin Protection is a straightforward process. You can use the AddTrustedOrigin method to allow all requests with an Origin header that exactly matches the given value. Origin header values are of the form "scheme://host[:port]".
This method can be called concurrently with other methods or request handling, and applies to future requests. You can call it multiple times to add multiple trusted origins.
For example, if you want to allow requests from the origin "https://example.com:8080", you can call AddTrustedOrigin with the value "https://example.com:8080".
Explore further: Golang Https
Config in 1.24.0
In Go 1.24.0, the HTTP2Config type was added to define HTTP/2 configuration parameters common to both Transport and Server.
HTTP2Config is a new feature in this version, and it's worth noting that it's been added to improve HTTP/2 configuration.
HTTP/2 configuration parameters are now more structured and easier to manage with HTTP2Config.
The HTTP1 function in Protocols was also added in Go 1.24.0, and it reports whether a protocol includes HTTP/1.
HTTP1 is a useful function for developers to check if a protocol supports HTTP/1.
Allow Semicolons in 1.17
In Go 1.17, a change was made that can cause issues with some proxies.
This change is related to how query parameters are split in URLs.
The pre-Go 1.17 behavior of splitting query parameters on both semicolons and ampersands was restored by the AllowQuerySemicolons function.
This function should be invoked before Request.ParseForm is called.
If you're experiencing issues with semicolons in your URLs, you can use the AllowQuerySemicolons function to fix the problem.
It's a simple solution that can help you avoid security issues caused by the mismatch in behavior between your application and some proxies.
Headers and Protocols
Headers and protocols are fundamental components of the HTTP protocol, allowing for efficient and standardized communication between clients and servers.
The canonical format of a header key is returned by the CanonicalHeaderKey function, which converts the first letter and any letter following a hyphen to upper case, and the rest to lowercase. For example, the canonical key for "accept-encoding" is "Accept-Encoding".
Headers are represented by the Header type, which stores key-value pairs in an HTTP header. Keys should be in canonical form, as returned by CanonicalHeaderKey.
Textproto.CanonicalMIMEHeaderKey is used to canonicalize the provided key in the Header type. This ensures that keys are always in the correct format for the Header type.
The Header type has several methods, including Set, Del, Get, and Values, which allow you to add, delete, get, and retrieve values associated with a key. These methods are case insensitive and use CanonicalHeaderKey to canonicalize the provided key.
Here is a summary of the methods available for the Header type:
Protocols are supported by the Protocols type, which includes HTTP1, HTTP2, and UnencryptedHTTP2. The HTTP1 protocol is supported on both unsecured TCP and secured TLS connections.
ParseForm
ParseForm is a method that populates the request's form and post form data. It's a crucial part of handling form data in Go.
For all requests, ParseForm parses the raw query from the URL and updates the request's form. This means that any query parameters will be available in the request's form.
ParseForm also reads the request body and parses it as a form for POST, PUT, and PATCH requests. This is where things get interesting - request body parameters take precedence over URL query string values in the request's form.
The request body is capped at 10MB unless a MaxBytesReader has already limited its size. This is a good thing, as it prevents overly large requests from crashing your server.
If this caught your attention, see: Golang Post
Request.ParseMultipartForm calls ParseForm automatically, making it easy to work with multipart form data. And the best part? ParseForm is idempotent, meaning you can call it multiple times without worrying about it doing anything funny.
Here's a quick rundown of the precedence order for form values:
- Application/x-www-form-urlencoded form body (POST, PUT, PATCH only)
- Query parameters (always)
- Multipart/form-data form body (always)
This order makes sense, as it prioritizes the most specific and relevant form data. And with ParseForm handling the heavy lifting, you can focus on what really matters - building a great application.
ProtoAtLeast
ProtoAtLeast is a useful method for checking the HTTP protocol used in a request or response. It takes a major and minor version number as an argument and reports whether the protocol is at least that version.
The method can be used to check if the request or response uses a protocol that is at least a certain version. For example, you can use it to check if the request uses HTTP/1.1 or later.
As noted in the documentation, the method returns true if the protocol is at least the specified version, and false otherwise. This can be useful for checking if a request or response is compatible with a certain version of the protocol.
In practice, you can use ProtoAtLeast to check if a request or response meets certain requirements. For example, you might use it to check if a request uses a protocol that supports certain features.
Referer
The Referer field in HTTP requests is a bit of a historical oddity, with a misspelling that's been carried over from the early days of the protocol. It's spelled "Referer" instead of "Referrer".
This field is used to indicate the URL of the page that made the current request. In other words, it's the URL of the page that the user was on before they clicked a link to get to the current page.
The Referer field can be accessed as a method, which is useful for catching spelling mistakes in your code. If you try to call req.Referrer() instead of req.Referer(), the compiler will give you an error.
You can also access the Referer field directly from the Header map as Header["Referer"]. This is useful if you need to access the field in a specific way.
Precedence
Precedence is a crucial aspect of how patterns match requests in ServeMux. If two or more patterns match a request, then the most specific pattern takes precedence.
A pattern P1 is more specific than P2 if P1 matches a strict subset of P2’s requests. This means that if P2 matches all the requests of P1 and more, then P1 is less specific.
If neither pattern is more specific, then the patterns conflict. There is one exception to this rule: if two patterns would otherwise conflict and one has a host while the other does not, then the pattern with the host takes precedence.
This rule is illustrated in the example of the patterns "GET /" and "/index.html". Both match a GET request for "/index.html", but the former pattern matches all other GET and HEAD requests, while the latter matches any request for "/index.html" that uses a different method. The patterns conflict.
Sanitizing
Sanitizing is an important aspect of handling requests in certain functions. ServeFileFS sanitizes the provided name before calling it, as a precaution against unsanitized user input.

If a name is constructed from user input, it's essential to sanitize it before passing it to ServeFileFS to prevent potential security issues. This is crucial because ServeFileFS will reject requests where r.URL.Path contains a ".." path element.
ServeMux also takes care of sanitizing the URL request path and the Host header. It strips the port number and redirects any request containing . or .. segments or repeated slashes to an equivalent, cleaner URL. Escaped path elements such as "%2e" for "." and "%2f" for "/" are preserved and aren't considered separators for request routing.
As for cookies, AddCookie only sanitizes the name and value of the cookie, but doesn't sanitize a Cookie header already present in the request.
For your interest: T Golang
Headers and Protocols
Headers and Protocols are crucial components of the HTTP protocol in Go. A Header represents the key-value pairs in an HTTP header, and the keys should be in canonical form.
The Header type has two important methods: Set and Get. Set sets the header entries associated with a key to a single element value, replacing any existing values, while Get gets the first value associated with a given key, returning an empty string if there are no values associated with the key.
Headers can be accessed directly, but it's recommended to use the canonicalized key to avoid any issues. The Get method assumes that all keys are stored in canonical form, so it's essential to keep that in mind when working with headers.
Now, let's take a look at the Protocols type. It represents the supported protocols in Go, which include HTTP1, HTTP2, and UnencryptedHTTP2. The HTTP1 protocol supports both unsecured TCP and secured TLS connections.
Here's a brief summary of the supported protocols:
Headers and Protocols
Headers are a crucial part of HTTP communication, and in Go, they're represented by the `Header` type. A `Header` is essentially a map of key-value pairs, where the keys are in canonical form.
The `Header` type has a `Set` method that allows you to set the header entries associated with a key to a single value. This replaces any existing values associated with that key, and the key is case-insensitive.
The `Header` type also has a `Get` method that retrieves the first value associated with a given key. If there are no values associated with the key, `Get` returns an empty string. The key is also case-insensitive, and it's canonicalized using `textproto.CanonicalMIMEHeaderKey`.
Protocols in Go's HTTP client are represented by the `Protocols` type. This type has a field called `UnencryptedHTTP2` that reports whether a protocol includes unencrypted HTTP/2. This is useful for determining whether a connection is secure or not.
Here's a summary of the supported protocols in Go's HTTP client:
These protocols are supported by Go's HTTP client, and you can use them to make HTTP requests and handle responses.
Headers and Protocols
Headers are a crucial part of HTTP requests and responses, and in Go, they're represented by the Header type. A Header represents the key-value pairs in an HTTP header, and the keys should be in canonical form, as returned by CanonicalHeaderKey.
The Header type has two main methods: Set and Get. Set sets the header entries associated with a key to a single element value, replacing any existing values. Get gets the first value associated with a given key, and if there are no values associated with the key, it returns an empty string.
You can use the Header type to manipulate HTTP headers in your Go code. For example, you can use the Set method to add a new header entry or replace an existing one, and the Get method to retrieve the value of a header entry.
Here's a quick reference to the Header type methods:
On the other hand, protocols are the underlying communication mechanisms used by HTTP. In Go, the Protocols type represents the supported protocols, which include HTTP1, HTTP2, and UnencryptedHTTP2. The UnencryptedHTTP2 protocol is supported on unsecured TCP connections.
Headers and Protocols
Headers in golang http are represented by the type Header, which stores key-value pairs in an HTTP header. The keys should be in canonical form, as returned by CanonicalHeaderKey.
You can set a header entry associated with a key to a single element value using the Set method. This replaces any existing values associated with the key.
The Get method returns the first value associated with a given key. If there are no values associated with the key, Get returns an empty string.
Here is a summary of the Header type's methods:
Protocols in golang http are supported through the type Protocols. The supported protocols are HTTP1, HTTP2, and UnencryptedHTTP2.
The UnencryptedHTTP2 method reports whether a protocol includes unencrypted HTTP/2.
Response and Round Tripping
The Client and Transport return Responses from servers once the response headers have been received, with the response body streamed on demand as the Body field is read.
To process the response, we can access and read the Body field, allowing us to handle the response data as needed.
The package enables us to send HTTP requests to other servers, including setting headers and providing data in the request body, and processing the responses received, making it possible to do custom requests to other servers.
Response

The Response section of the HTTP package is where things get really interesting. A Response is essentially the data that's sent back to the client after a request has been made. The Client and Transport return Responses from servers once the response headers have been received, and the response body is streamed on demand as the Body field is read.
Responses can be used to send data back to the client in various ways, such as by using the ResponseWriter interface. This interface is used by an HTTP handler to construct an HTTP response. A ResponseWriter may not be used after the Handler.ServeHTTP method has returned.
You can also use the ResponseController to control the response. A ResponseController is used by an HTTP handler to control the response. It may not be used after the Handler.ServeHTTP method has returned. The ResponseController can be used to set the deadline for writing the response, and to enable full duplex mode, which allows the request handler to interleave reads from the request body with writes to the ResponseWriter.

Here's a list of some of the key methods and functions related to Responses:
- ResponseWriter: used by an HTTP handler to construct an HTTP response
- ResponseController: used by an HTTP handler to control the response
- SetWriteDeadline: sets the deadline for writing the response
- EnableFullDuplex: enables full duplex mode, allowing the request handler to interleave reads from the request body with writes to the ResponseWriter
In addition to these methods, you can also use the Response object itself to write data back to the client. For example, you can use the Write method to write an HTTP/1.1 request, which includes the header and body in wire format. The Write method consults the following fields of the request: Body, Content-Length, and TransferEncoding.
Response Location
The Location of a response is a crucial piece of information that can help clients navigate to the right page.
The Location of a response is returned by the Location method of the Response type.
If a response has a "Location" header, the Location method will return its URL.
Relative redirects are resolved relative to the Request of the Response.
If no Location header is present, the ErrNoLocation error is returned.
A ResponseWriter is used by an HTTP handler to construct an HTTP response, and it may not be used after the Handler.ServeHTTP method has returned.
The http.Redirect function adds an HTTP status code of http.StatusFound (302) and a Location header to the HTTP response.
This is useful when handling non-existent pages, as it redirects the client to the edit page to create new content.
Response and Round Tripping
The Client and Transport return Responses from servers once the response headers have been received. The response body is streamed on demand as the Body field is read.
Responses are returned from servers once the response headers have been received. This is a fundamental concept in working with HTTP requests and responses in Go.
We can access and process information from incoming HTTP requests, such as headers and the data sent in the request body, using the http package. This enables us to build custom requests to other servers.
The http package also allows us to construct and send HTTP requests to other servers, including setting headers, providing data in the request body, and processing the responses received. This is a powerful tool for working with HTTP in Go.
In an HTTP handler function, we can use a switch statement to identify the request method and execute different code blocks based on the method type. If the method is GET, we can handle the GET request accordingly.
If the method is POST, we can handle the POST request accordingly. If the method is anything other than GET or POST, we can respond by sending an 'Invalid request method' message back to the client using the http.Error function, along with a StatusMethodNotAllowed HTTP status code.
Response and Round Tripping
The http package in Go enables us to access and process information from incoming HTTP requests, including headers and the data sent in the request body.
We can construct and send HTTP requests to other servers, including setting headers, providing data in the request body, and processing the responses received. This means we can do custom requests to other servers.
The Client and Transport return Responses from servers once the response headers have been received. The response body is streamed on demand as the Body field is read.
In Go, we can handle requests and responses by defining an HTTP handler function for a specific route, such as the '/users' route. This function responds to incoming HTTP requests on that route, processing them according to the specific request method.
The handler function is designed to accept two arguments: ResponseWriter and Request. ResponseWriter is an interface that aids in sending data back to the client as a response.
If the request method is not GET or POST, the handler will respond with an 'Invalid request method' message and a StatusMethodNotAllowed HTTP status code.
Response and Round Tripping
The Client and Transport return Responses from servers once the response headers have been received. The response body is streamed on demand as the Body field is read.
You can access and process information from incoming HTTP requests, including headers and data sent in the request body, using the http package. This package also enables you to construct and send HTTP requests to other servers.
A ResponseWriter is an interface that aids in sending data back to the client as a response. This is used in HTTP handler functions to send data back to the client.
The http package allows you to handle different request methods, such as GET and POST, in your handler functions. You can use a switch statement to identify the request method and execute different code blocks accordingly.
If the request method is not GET or POST, you can respond with an 'Invalid request method' message and a StatusMethodNotAllowed HTTP status code using the http.Error function.
Transport and Connection
A Transport is a low-level primitive for making HTTP and HTTPS requests, designed for concurrent use by multiple goroutines and efficiency.
By default, Transport caches connections for future re-use, which may leave many open connections when accessing many hosts. This behavior can be managed using Transport.CloseIdleConnections method and the [Transport.MaxIdleConnsPerHost] and [Transport.DisableKeepAlives] fields.
Transports should be reused instead of created as needed, as creating a new Transport for each request can lead to inefficiencies.
Listen
ListenAndServe is a function that listens on a TCP network address and handles incoming connections. It's typically used with a handler, but if none is provided, it defaults to DefaultServeMux.
The handler is usually nil, which is the default behavior. Accepted connections are configured to enable TCP keep-alives, which is a feature that sends periodic messages to keep the connection alive.
ListenAndServe always returns a non-nil error, so you can expect an error message even if everything goes smoothly. This is because it's designed to handle errors, even if there aren't any.

If you're using a Server object, you can call its ListenAndServe method to start listening. This method listens on the TCP network address specified by s.Addr, or defaults to ":http" if that's blank.
After calling Server.Shutdown or Server.Close, the returned error is ErrServerClosed, which indicates that the server has been closed.
ListenAndTLS
ListenAndServeTLS is a function that listens on the TCP network address s.Addr and then calls ServeTLS to handle requests on incoming TLS connections.
Accepted connections are configured to enable TCP keep-alives. This means that even if the connection is idle for a period of time, the server will still periodically send a "keep-alive" message to the client to keep the connection alive.
Filenames containing a certificate and matching private key for the server must be provided if neither the Server's TLSConfig.Certificates nor TLSConfig.GetCertificate are populated.
If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. This is important for ensuring that the client can verify the server's identity.
ListenAndServeTLS always returns a non-nil error. After Server.Shutdown or Server.Close, the returned error is ErrServerClosed. This means that you should always check the error returned by ListenAndServeTLS to ensure that it was successful.
Proxyurl

ProxyURL returns a proxy function that always returns the same URL.
This function is useful when you need to use a specific proxy for all requests, rather than letting the environment variables decide. The proxy function returned by ProxyURL can be used in a Transport to always use the same proxy URL.
If you need to use a proxy for all requests, you can use the proxy function returned by ProxyURL. This is a convenient way to avoid having to set environment variables for each request.
The proxy function returned by ProxyURL is a simple and effective way to use a proxy for all requests. It's a good option when you need to use a specific proxy for all your requests.
Here's an interesting read: Golang Proxy
Transport
Transport is a low-level primitive for making HTTP and HTTPS requests. It's a crucial component of the net/http package, allowing you to send and receive data over the web.
A Transport is safe for concurrent use by multiple goroutines, making it a great choice for high-performance applications. It also supports HTTP/1.1 and HTTP/2 protocols, depending on the server's capabilities and the Transport's configuration.
By default, Transport caches connections for future re-use, which can leave many open connections when accessing many hosts. To manage this behavior, you can use the Transport.CloseIdleConnections method, as well as the MaxIdleConnsPerHost and DisableKeepAlives fields.
Here's a quick rundown of the Transport's key features:
Transport also provides a Clone method, which returns a deep copy of the Transport's exported fields. This can be useful when you need to create a new Transport with the same settings as an existing one.
By reusing Transports instead of creating new ones as needed, you can improve the performance and efficiency of your application.
For more insights, see: Golang Http New Request
Read Deadline
Setting a read deadline is crucial for handling incoming requests, especially when dealing with large amounts of data.
You can set the read deadline using the SetReadDeadline function, which is available in the ResponseController type since Go 1.20.
A zero value for the deadline means no deadline is set, and reads from the request body will not return an error.
However, setting the read deadline after it's been exceeded will not extend it, so make sure to set it before the deadline is reached.
ListenTLS
ListenTLS is a function that acts identically to ListenAndServe, except that it expects HTTPS connections. This means it's used to serve HTTPS requests.
To use ListenTLS, you'll need to provide files containing a certificate and matching private key for the server. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate, any intermediates, and the CA's certificate.
ListenTLS always returns a non-nil error. After Server.Shutdown or Server.Close, the returned error is ErrServerClosed. This is the same behavior as ListenAndServe.
ListenTLS is typically used to serve HTTPS connections, and it's a good idea to reuse the same Transport instance to improve efficiency. This is because Transports are safe for concurrent use by multiple goroutines and should be reused instead of created as needed.
Introducing the Net Package
The net/http package is a fundamental part of Go's standard library, allowing you to create web servers and handle HTTP requests with ease.
You can create a simple web server using the http.HandleFunc function, which tells the http package to handle all requests to the web root ("/") with a handler function.
To listen on a specific port, you use the http.ListenAndServe function, specifying the port number and any interface you want to listen on. For example, listening on port 8080 is as simple as calling ListenAndServe with ":8080".
The handler function is of the type http.HandlerFunc and takes an http.ResponseWriter and an http.Request as its arguments. The http.ResponseWriter value assembles the HTTP server's response, allowing you to send data to the HTTP client by writing to it.
An http.Request represents the client HTTP request, and its URL.Path property gives you the path component of the request URL. By using the [1:] syntax, you can drop the leading "/" from the path name, making it easier to work with.
If you run a program with this setup and access the URL, it will present a page containing the data you've written to the http.ResponseWriter.
Consider reading: Golang Web Programming
Transport and Connection
Transport is a low-level primitive for making HTTP and HTTPS requests, and it's a crucial component in the Go HTTP ecosystem.
It's designed to be reused instead of created as needed, and it's safe for concurrent use by multiple goroutines.
A Transport is an implementation of RoundTripper that supports HTTP, HTTPS, and HTTP proxies, and it caches connections for future re-use by default.
This caching behavior can be managed using the Transport.CloseIdleConnections method and the Transport.MaxIdleConnsPerHost and Transport.DisableKeepAlives fields.
Transports should be reused instead of created as needed, which can help improve efficiency and reduce the number of open connections.
Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2 for HTTPS URLs, depending on whether the server supports HTTP/2 and how the Transport is configured.
The DefaultTransport supports HTTP/2, and you can explicitly enable HTTP/2 on a transport by setting the Transport.Protocols field.
Responses with status codes in the 1xx range are either handled automatically or ignored, with the exception of HTTP status code 101 (Switching Protocols), which is considered a terminal status and returned by Transport.RoundTrip.
Transport only retries a request upon encountering a network error if the connection has been already been used successfully and if the request is idempotent and either has no body or has its Request.GetBody defined.
Transport and Connection
A Transport is a low-level primitive for making HTTP and HTTPS requests.
It's a crucial component for handling connections and managing settings for your GoLang HTTP applications.
By default, Transport caches connections for future re-use, which can leave many open connections when accessing many hosts.
This behavior can be managed using Transport.CloseIdleConnections method and the [Transport.MaxIdleConnsPerHost] and [Transport.DisableKeepAlives] fields.
Transports are safe for concurrent use by multiple goroutines, making them a great choice for high-traffic applications.
This means you can reuse the same Transport instance across multiple goroutines without worrying about thread safety issues.
To see the ignored 1xx responses, use the httptrace trace package's ClientTrace.Got1xxResponse.
This can be especially useful for debugging purposes.
A Transport only retries a request upon encountering a network error if the connection has been already been used successfully and if the request is idempotent and either has no body or has its Request.GetBody defined.
This means you can take advantage of connection reuse to improve performance.
Transports should be reused instead of created as needed, for efficiency and to avoid creating too many open connections.
This is a best practice to follow when working with GoLang HTTP.
Error Handling and Middleware
Error handling is crucial in Go's http package, and it's essential to handle errors instead of ignoring them. This way, if something goes wrong, the server will function as intended and the user will be notified.
The http.Error function sends a specified HTTP response code and error message, making it a useful tool for error handling. It's already been mentioned that this function is used in the renderTemplate function.
Any errors that occur during p.save() will be reported to the user, ensuring a better user experience. This is a great example of how error handling can be implemented in a practical way.
Middleware is another powerful tool in Go's http package, allowing you to add additional functionality to your HTTP server's request processing pipeline.
Middleware & Auth
Middleware is like a filter that can be used to add extra functionality to your HTTP server's request processing pipeline. It can be used for logging, authorization, or rate-limiting. Middleware functions can intercept requests and responses, perform additional processing, and pass the request to the next middleware or handler.
Broaden your view: Golang Http Middleware
Middleware allows you to add additional functionality to your HTTP server's request processing pipeline, making it easier to manage and secure your application. This can include things like logging requests and responses, or ensuring that only authenticated users can access certain routes.
The http.Handler interface is used to chain multiple middleware functions together, allowing you to create complex request processing pipelines. This is useful for handling multiple routes and providing data as a response to client requests.
Middleware can be used to modify the behavior of an HTTP server or client, making it a powerful tool for managing and securing your application. By using middleware, you can create a more robust and reliable application that is better equipped to handle a wide range of requests and scenarios.
The package provides the http.Handler interface that allows you to chain multiple middleware functions together. This is useful for handling multiple routes and providing data as a response to client requests.
HTTP Basic Authentication can be used to authenticate users by checking the username and password provided in the request's Authorization header. This is useful for securing routes that require authentication.
The SetBasicAuth function sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password. This is useful for authenticating users and securing routes that require authentication.
BasicAuth returns the username and password provided in the request's Authorization header, if the request uses HTTP Basic Authentication. This is useful for authenticating users and securing routes that require authentication.
HTTP Basic Authentication is not encrypted, so it should generally only be used in an HTTPS request. This is because the username and password are sent in plain text, making them vulnerable to interception.
Hijacker
The Hijacker interface is implemented by ResponseWriters that allow an HTTP handler to take over the connection.
Not all ResponseWriters support the Hijacker interface, with HTTP/2 connections intentionally not supporting it.
ResponseWriter wrappers may also not support Hijacker, so handlers should always test for this ability at runtime.
The Hijack function, added in Go 1.20, lets the caller take over the connection, and you can see the Hijacker interface for details on how it works.
Handlers should check if the ResponseWriter supports Hijack before trying to use it, to avoid any potential issues.
Write Deadline
Writing to a deadline can be a delicate matter, especially when it comes to sending responses. A zero value means no deadline.
Setting a write deadline is crucial for preventing blocked writes to the response body. Writes to the response body after the deadline has been exceeded will not block, but may succeed if the data has been buffered.
You can't extend a write deadline once it's been exceeded, so set it wisely. Setting the write deadline after it has been exceeded will not extend it.
Cancel
Canceling requests is a crucial aspect of error handling and middleware. CancelRequest is a deprecated method that cancels an in-flight request by closing its connection.
It should only be called after Transport.RoundTrip has returned. This is because CancelRequest cannot cancel HTTP/2 requests.
Use Request.WithContext to create a request with a cancelable context instead. CancelRequest may become a no-op in a future release of Go.
Error Handling and Middleware
Error handling is crucial in any program, and in Go, you can use the http.Error function to send a specified HTTP response code and error message to the user.
Ignoring errors is a bad practice, and it can lead to unintended behavior in your program.
To handle errors effectively, you can use a separate function, like the one used in renderTemplate, which sends an "Internal Server Error" response code and error message.
Any errors that occur during p.save() will be reported to the user, making it easier to track and fix issues.
Middleware allows you to add additional functionality to your HTTP server's request processing pipeline, enabling you to log requests and responses, ensure only authenticated users can access certain routes, or control the number of requests from a specific client.
Middleware functions can intercept requests and responses, perform additional processing, and pass the request to the next middleware or handler.
The http.Handler interface allows you to chain multiple middleware functions together, making it easier to manage complex request handling and response management.
On a similar theme: Golang Message
Error Handling and Middleware
Error handling is a crucial aspect of building a robust HTTP server. It involves catching and reporting errors to the user, ensuring the server functions as intended.
Ignoring errors can lead to unintended behavior and a poor user experience. A better approach is to handle errors and return an error message to the user.
The http.Error function sends a specified HTTP response code and error message, which is already implemented in the renderTemplate function. This function is a great example of how to handle errors effectively.
Any errors that occur during p.save() will be reported to the user, providing a clear and transparent experience.
Middleware is another powerful tool for adding functionality to the HTTP server's request processing pipeline. It allows us to log requests and responses, ensure only authenticated users access certain routes, or control the number of requests from a specific client.
Middleware functions can intercept requests and responses, perform additional processing, and pass the request to the next middleware or handler. This can be achieved by chaining multiple middleware functions together.
In Go, we can use the http.Handler interface to define middleware functions for each handler. This interface allows us to modify the behavior of the HTTP server or client by intercepting requests and responses.
Middleware functions can be used to take data from a remote server and pass it to the handler, which can then send the response to the client. This is a great way to add additional functionality to our HTTP server without modifying the underlying code.
Routing
Routing is a crucial aspect of building HTTP servers in Go. We can define routes and route handlers for different URL patterns using the http.HandleFunc function.
This function allows us to register a handler function for a specific URL pattern. For example, we can use it to define a handler function for the root URL ("/") that responds with a specific message.
Alternatively, we can use the http.ServeMux type to create a custom router with more advanced routing capabilities. This approach gives us more flexibility in handling different routes and their corresponding handlers.
In a real-world scenario, we might want to handle multiple routes with different responses. For instance, we can use the http.HandleFunc function to define a handler function for the "/users" URL that responds with a different message.
By using these techniques, we can create a robust and efficient routing system for our Go HTTP servers. This enables us to handle a wide range of requests and responses in a scalable manner.
Routing and Middleware
Routing and Middleware are two essential components of a GoLang HTTP server.
Middleware allows us to add additional functionality to our HTTP server's request processing pipeline, such as logging, authorization, and rate-limiting.
We can use middleware to modify the behavior of an HTTP server or client by intercepting requests and responses, performing additional processing, and passing the request to the next middleware or handler.
For example, we can use middleware to take the request and get data from a remote server, then pass the data to the handler, which sends the response to the client.
To define routes and route handlers for different URL patterns, we can use the http.HandleFunc function to register a handler function for a specific URL pattern.
Alternatively, we can use the http.ServeMux type to create a custom router with more advanced routing capabilities.
In a real-world scenario, we can extend the previous HTTP server example to handle multiple routes, responding with different messages based on the URL path.
For instance, for the root (“/”) URL, we can respond with “Hello, Emon!”, and for the “/users” URL, we can respond with “Welcome to Emon’s blog!”.
The http.Handler interface allows us to chain multiple middleware functions together, making it easy to add or remove middleware as needed.
By using middleware and routing effectively, we can create a robust and scalable HTTP server that meets the needs of our application.
Routing and Middleware
Routing and Middleware are two essential components of the GoLang http package.
You can define routes and route handlers for different URL patterns using the http.HandleFunc function.
This function allows you to register a handler function for a specific URL pattern. For example, you can define a handler function for the root URL ("/") and another for the "/users" URL.
You can also use the http.ServeMux type to create a custom router with more advanced routing capabilities.
Middleware functions can intercept requests and responses, perform additional processing, and pass the request to the next middleware or handler.
You can chain multiple middleware functions together using the http.Handler interface.
This allows you to add additional functionality to your HTTP server's request processing pipeline. For example, you can use logging middleware to log requests and responses, or authorization middleware to ensure only authenticated users can access certain routes.
You can also use rate-limiting middleware to control the number of requests from a specific client.
In a real-world scenario, you might want to use middleware to retrieve data from a remote server and pass it to the handler function. This way, the handler function can modify the request or response as needed.
For instance, you can define a handler function for each route and use middleware to retrieve data from a remote server before passing it to the handler function.
Worth a look: Golang Pass
This approach allows you to decouple the handling of requests and responses from the retrieval of data, making your code more modular and maintainable.
You can see this approach in action in the example of the HTTP Server with routing, where the server responds with different messages based on the URL path.
You might enjoy: Simple Http Server Golang Github
Featured Images: pexels.com


