mist

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2024 License: MIT Imports: 18 Imported by: 2

README

mist

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	Request        *http.Request       // The HTTP request object
	ResponseWriter http.ResponseWriter // The writer to send HTTP responses
	PathParams     map[string]string   // URL path parameters

	MatchedRoute   string // The matched route pattern
	RespData       []byte // Response data to be written to the client
	RespStatusCode int    // HTTP response status code

	UserValues map[string]any // Additional user-defined values to pass through the context
	// contains filtered or unexported fields
}

Context holds all the essential information required for processing an HTTP request. It contains the actual HTTP request, a writer to send the response, path parameters extracted from the URL, query parameters, the route that matched the request, the response data and status code to return to the client, a template engine for rendering views, and a general-purpose map to hold any user-defined values.

func (*Context) BindJSON

func (c *Context) BindJSON(val any) error

BindJSON deserializes the JSON-encoded request body into the provided value. It is often used in the context of HTTP handlers to parse incoming JSON data into a Go data structure.

Parameters:

  • 'val' is a pointer to any Go data structure into which the JSON body of the request will be decoded. This argument must be a non-nil pointer that points to an allocatable or allocated value so that the JSON package can populate the fields of the structure. It must not be nil, as passing nil does not provide a storage location for the decoded data.

The function execution involves the following steps:

  1. It checks if 'val' is nil. If it is, no storage is allocated for the JSON data to be decoded into, so it returns an error using 'errs.ErrInputNil()', indicating that the input value cannot be nil.
  2. It checks if 'c.Request.Body' is nil. If the body is nil, there is no data to decode, and it returns an error using 'errs.ErrBodyNil()', signaling that there is no request body to parse.
  3. It creates a new JSON decoder for the request body and performs the decoding operation using 'decoder.Decode(val)'. If the JSON data in the request body is not well-formed or does not match the expected structure of 'val', json.Decoder will return a relevant error to inform the call site about the issue.

Return Value: - If the decoding is successful, it returns 'nil', indicating that the JSON data has been successfully bound to 'val'. - If an error occurs during decoding, it returns the error, indicating an issue with input validation or the decoding process.

Usage:

  • This method is useful when you want to automatically handle the parsing of JSON data into a Go data structure from an HTTP request. It abstracts away the low-level streaming and decoding of JSON.

Example: - To bind the JSON body of an HTTP request to a struct:

type UserInput struct {
   Name  string `json:"name"`
   Email string `json:"email"`
}

var userInput
if err := c.BindJSON(&userInput); err != nil {
   // handle the error (e.g., send an HTTP 400 Bad Request response)
}

Note:

  • The 'BindJSON' method should be called before accessing the request body by any other means, as the body is an io.ReadCloser and can generally only be read once. Reading the body elsewhere before calling 'BindJSON' will likely result in an EOF error.

func (*Context) BindJSONOpt

func (c *Context) BindJSONOpt(val any, useNumber bool, disableUnknown bool) error

BindJSONOpt deserializes the JSON-encoded request body into the provided value with options to use JSON numbers and disallow unknown fields. This function extends the BindJSON method by providing additional decoding options that can be enabled as needed.

Parameters:

  • 'val' is a pointer to any Go data structure into which the JSON body of the request will be decoded. It must be a non-nil pointer, so it can be populated with decoded data. Passing a nil pointer will result in an error since there would be no allocated structure to decode the data into.
  • 'useNumber' is a boolean option that, when set to true, tells the decoder to decode numbers into an interface{} as a json.Number instead of as a float64. This is useful when precision for large integers is necessary or when the numeric values need to be unmarshalled into a specific typed variable later.
  • 'disableUnknown' is a boolean option that, when set to true, causes the decoder to return an error if it encounters any unknown fields in the JSON data that do not match any fields in the target Go data structure. This can be useful for strict input validation.

The function performs the following steps:

  1. It verifies that 'val' is not nil. If it is nil, it returns an error signaling that a valid pointer is required.
  2. It checks if 'c.Request.Body' is nil, which would indicate that there is no data to decode, and returns an error if this is the case.
  3. It initializes a JSON decoder for the request body. The decoder then checks the 'useNumber' and 'disableUnknown' options to configure its behavior accordingly: a. If 'useNumber' is true, it configures the decoder to treat numbers as json.Number types instead of defaulting them to float64. b. If 'disableUnknown' is true, it configures the decoder to reject unknown fields.
  4. It attempts to decode the JSON request body into 'val'. If the decoding is unsuccessful (for example, due to JSON syntax errors, mismatch between the JSON data and 'val' structure, etc.), it returns the error resulting from the decoder.

Return Value: - Returns 'nil' if the JSON request body has been successfully decoded into 'val'. - Returns an error if 'val' is nil, if there is no request body, or if the JSON decoding process encounters an error.

Usage: - This method is useful for controlling the JSON decoding process in HTTP handlers where there may be a need for more strict or lenient JSON parsing.

Example: - To bind a JSON body to a struct with strict type preservation and unknown field rejection:

type UserInput struct {
   Name string `json:"name"`
   Age  json.Number `json:"age"`
}

var userInput
err := c.BindJSONOpt(&userInput, true, true)
if err != nil {
   // handle the error (e.g., send an HTTP 400 Bad Request response)
}

Note:

  • Similar to BindJSON, BindJSONOpt should be called before any other form of accessing the request body is performed, as it is an io.ReadCloser that allows for a single read operation. This means that calling BindJSONOpt after the body has been read will likely result in an EOF error.

func (*Context) FormValue

func (c *Context) FormValue(key string) StringValue

FormValue extracts a value from the form data in an HTTP request based on the given key. It parses the URL-encoded form data (both in the URL query string and the request body) and retrieves the value associated with the provided key.

Parameters: - 'key' is a string representing the name of the form value to be retrieved from the HTTP request.

The function performs the following actions:

  1. It calls 'c.Request.ParseForm()' to parse the request body as a URL-encoded form. This is necessary to populate 'c.Request.Form' with the form data. This method also parses the query parameters from the URL, merging them into the form values. If parsing fails (for example, if the body can't be read, is too large, or if the content type is not application/x-www-form-urlencoded), an error is returned.
  2. If 'ParseForm()' returns an error, the function creates a 'StringValue' instance with an empty string for 'val' and the parsing error for 'err'. It then returns this 'StringValue' containing the error information.
  3. If 'ParseForm()' succeeds, 'c.Request.FormValue(key)' is used to retrieve the first value for the specified key from the merged form data. A 'StringValue' instance is then returned with the retrieved value and 'nil' for the error.

Return Value:

  • A 'StringValue' instance is always returned. This struct contains two fields: a. 'val' which is the string value retrieved from the form data. b. 'err' which captures any error that may have occurred during the parsing of the form data.

Usage: - This method is intended to be used in HTTP handlers when you need to access form values sent in an HTTP request.

Example: - To retrieve a form value named "email" from an HTTP request:

email := c.FormValue("email")
if email.err != nil {
   // handle the error (e.g., send an HTTP 400 Bad Request response)
}
// Use email.val as the required string value for "email".

Note:

  • The 'FormValue' method does not handle multiple values for the same key. It only retrieves the first such value.
  • Calling 'FormValue' multiple times on the same request is safe as it does not reparse the form data. The form data is parsed only once, and subsequent calls will retrieve values from the already parsed form.
  • The 'ParseForm' method can only parse the request body if the method is "POST" or "PUT" and the content type is "application/x-www-form-urlencoded". For other HTTP methods or content types, the body will not be parsed, but URL query parameters will still be available.

Considerations: - Ensure that the 'ParseForm' method is not called before any other method that might consume the request body, as the request body is typically read-only once.

func (*Context) PathValue

func (c *Context) PathValue(key string) StringValue

PathValue retrieves a value from the path parameters of an HTTP request based on the given key. The path parameters are typically extracted from the URL path, where they are defined by the routing patterns used in the application.

Parameters: - 'key': A string representing the name of the path parameter to be retrieved.

The function performs the following actions:

  1. It checks if the map 'c.PathParams' contains the key provided in the method parameter. 'c.PathParams' is expected to be populated with key-value pairs where keys correspond to path parameter names defined in the URL pattern, and values are the respective parameters extracted from the actual request URL.
  2. If the key is present in 'c.PathParams', it retrieves the corresponding value, wraps it in a 'StringValue' struct by setting the 'val' field to the retrieved value and 'err' field to nil, and then returns it.
  3. If the key is not found, it means the requested path parameter is not present in the request URL. In this case, the method returns a 'StringValue' struct with 'val' set to an empty string and 'err' set to an error instance that typically indicates the absence of the key.

Return Value:

  • A 'StringValue' struct that contains the value associated with the provided key ('val') and an error field ('err'). If the key is not present, the 'err' field contains an appropriate error while 'val' is an empty string.

Usage: - This method is useful in web server routing where URL paths may contain parameters that need to be extracted and used within the application logic.

Example: - Assuming a URL pattern like "/users/:id" where :id is a path parameter:

userID := c.PathValue("id")
if userID.err != nil {
   // handle the error (e.g., send an HTTP 404 Not Found response)
}
// Use userID.val as the required user ID string value.

Note:

  • The method assumes that 'c.PathParams' has already been populated with the correct path parameters before calling 'PathValue'. In a typical web server implementation, this population is done during the routing process, before the request handler is invoked.
  • The 'PathParams' may hold multiple path parameters depending on the URL pattern; 'PathValue' method is responsible for extracting a single parameter by key.
  • If the same key would be present multiple times in 'c.PathParams', this method would return the first instance of the value associated with the key.

Considerations:

  • When working with frameworks or routers that facilitate path parameter extraction, ensure the router is correctly configured to parse and store the path parameters before calling this method.

func (*Context) QueryValue

func (c *Context) QueryValue(key string) StringValue

QueryValue retrieves the first value associated with the specified key from the URL query parameters of an HTTP request.

Parameters: - 'key' is the string that specifies the key in the query parameter that we want to retrieve the value for.

This function operates as follows:

  1. Checks if 'c.queryValues' is already populated. If it is not, it initializes it with the parsed query parameters obtained by calling 'c.Request.URL.Query()'. This method parses the raw query from the URL and returns a map of the query parameters.
  2. It looks for the given 'key' in 'c.queryValues' to see if it exists. The values are stored in a slice of strings because URL query parameters can have multiple values.
  3. If the key does not exist in the map, it implies that the parameter was not supplied in the query string. In this case, the function returns a 'StringValue' struct with an empty string for the 'val' field and an 'ErrKeyNil' error for the 'err' field.
  4. If the key is present, the function returns a 'StringValue' struct with the first value associated with the key and 'nil' for the 'err' field.

Return Value:

  • A 'StringValue' struct is always returned. It contains: a. 'val', the value associated with the provided key from the query parameters. b. 'err', an error if the key is not found in the query parameters.

Usage: - The method is ideal when you need to obtain individual query parameters from an HTTP request without parsing the entire URL query string manually.

Example: - To retrieve a query parameter named "page" from an HTTP request:

page := c.QueryValue("page")
if page.err != nil {
   // handle the error (e.g., the "page" query parameter was not provided)
}
// Use page.val to work with the value of "page".

Note:

  • This function only retrieves the first value for the specified key even if there are multiple values for that key.
  • 'c.queryValues' is cached after its first use, which improves performance when accessing multiple query parameters since it avoids reparsing the query string of the URL.
  • It is important to correctly handle the error scenario since a missing key in the query parameters can affect application logic.

Considerations: - While handling query data, consider the URL's sensitivity and the possibility of multiple values. Always validate and clean data from URL queries to ensure security.

func (*Context) Render

func (c *Context) Render(templateName string, data any) error

Render processes a template and populates it with dynamic data provided by the 'data' parameter. The method first attempts to render the specified template by calling the rendering engine bound to the context.

Parameters:

  • 'templateName' is the name of the template that should be rendered. It is expected that this template has been defined and is recognizable by the template engine.
  • 'data' is an interface{} type, which means it can accept any value that conforms to Go's empty interface. This is the dynamic content that will be injected into the template during rendering.

The rendered template output is captured and assigned to 'c.RespData'. This output will typically be HTML or another text format suitable for the client's response.

If the rendering operation is successful, the response status code is set to HTTP 200 (OK) indicating the request has been successfully processed and the client can expect valid content.

If an error occurs during the rendering operation (such as if the template is not found, or if there is a problem with the template's syntax), the response status code is set to HTTP 500 (Internal Server Error), and the error is returned to the caller. This error should be handled appropriately by the caller, possibly by logging it or presenting a user-friendly error message to the end-user.

Return Value: Returns 'nil' if rendering succeeds without any error, otherwise an error object describing the rendering failure is returned.

func (*Context) RespJSON

func (c *Context) RespJSON(status int, val any) error

RespJSON sends a JSON-formatted response to the client with a specified HTTP status code. It converts the provided value to JSON, sets the response headers, and writes the JSON data to the response.

Parameters:

  • 'status' is an integer that represents the HTTP status code to send with the response. Standard HTTP status codes should be used (e.g., 200 for OK, 400 for Bad Request, 404 for Not Found, etc.).
  • 'val' is an interface{} (any type) that holds the data to be serialized into JSON. This can be any Go data structure such as structs, slices, maps, etc. The value provided must be a valid input for the json.Marshal function, which means it should be able to be encoded into JSON. Non-exported struct fields will be omitted by the marshaller.

This function performs several actions:

  1. It uses the 'json.Marshal' function to serialize the 'val' parameter into a JSON-formatted byte slice 'data'. If marshaling fails, it returns the resultant error without writing anything to the response.
  2. Assuming marshaling is successful, it sets the "Content-Type" header of the response to "application/json" to inform the client that the server is returning JSON-formatted data.
  3. It sets the "Content-Length" header to the length of the serialized JSON data, which helps the client understand how much data is being transmitted.
  4. It writes the HTTP status code to the response using WriteHeader(status). This must be done before writing the response body.
  5. Lastly, it assigns the JSON data to 'c.RespData' and the status code to 'c.RespStatusCode' for later use or inspection.

Return Value: - If the JSON serialization and writing to the response are successful, it returns 'nil', indicating that the operation completed without error. - If an error occurs during JSON serialization, the error is returned, and no further action is taken.

Usage: - This method is designed to be used in HTTP handler functions where a JSON response is needed. It abstracts away the common tasks of JSON serialization, header setting, and response writing.

Example: - To send an object with an OK (200) status code:

data := map[string]string{"status": "success"}
err := c.RespJSON(http.StatusOK, data)
if err != nil {
   log.Printf("Error sending JSON response: %v", err)
   // handle the error, like sending a 500 Internal Server Error status code
}

Note:

  • It is important to note that once the 'WriteHeader' method is called, it's not possible to change the response status code or write any new headers. Also, care must be taken to ensure that 'RespJSON' is not called after the response body has started to be written by other means, as this would result in an HTTP protocol error.

func (*Context) RespJSONOK

func (c *Context) RespJSONOK(val any) error

RespJSONOK sends a JSON response with an HTTP status code 200 (OK) to the client. This is a convenience method that wraps around the more general 'RespJSON' method, abstracting the common case of responding with an OK status.

Parameters:

  • 'val' is the data of any type that will be serialized into JSON format. The 'val' can be any Go data structure, including structs, maps, slices, and primitive types. It is important that the 'val' can be marshaled into JSON; otherwise, the serialization will fail.

Internally, 'RespJSONOK' calls the 'RespJSON' method on the same context instance 'c', passing in 'http.StatusOK' as the status code and 'val' as the value to be serialized.

The 'RespJSON' method handles the serialization of 'val' to JSON, sets the "Content-Type" response header to "application/json", and writes the JSON-encoded data to the response along with the provided HTTP status code.

Return Value: - If the serialization into JSON is successful and the response is written to the client, it returns 'nil' indicating no error occurred. - In case of an error during JSON marshaling or writing to the response, it returns an error detailing the issue encountered.

Usage:

  • This method is typically used within an HTTP handler function when the server needs to send a JSON response back to the client with a 200 OK status code. This is usually the case when a request has been processed successfully, and server needs to inform the client of the success, often with accompanying data.

Example: - To send a simple success message in JSON format:

type response struct {
   Message string `json:"message"`
}

resp := response{Message: "Data processed successfully"}
err := c.RespJSONOK(resp)
if err != nil {
   // handle error
}

Note: - This method should be called after all response headers and status codes are set, and before any calls to write body content directly, as it will write data to the body and set headers.

func (*Context) SetCookie

func (c *Context) SetCookie(ck *http.Cookie)

SetCookie adds a Set-Cookie header to the response of the current HTTP context. This method is used to send cookies from the server to the client's web browser.

Parameters: - 'ck' is a pointer to an 'http.Cookie' object which represents the cookie you want to set. This object includes various fields that define the properties of a cookie, such as Name, Value, Path, Domain, Expires, and so on.

This function does not return any value or error, as it directly manipulates the HTTP headers of the response. It's essential to call SetCookie before writing any response body to the client because HTTP headers cannot be modified after the body starts to be written.

'http.SetCookie' is a standard library function that ensures the correct formatting of the Set-Cookie header. When calling this method, 'c.ResponseWriter' is used to gain access to the response writer associated with the current HTTP request handled by the context 'c'.

Usage:

  • This method is typically called within an HTTP handler function where you have an instance of the Context 'c' available. It is part of managing session data, sending tracking cookies, or setting any other kind of cookie data required by the application.

Example: - To set a session cookie with a session identifier:

sessionCookie := &http.Cookie{
   Name:    "session_id",
   Value:   "abc123",
   Expires: time.Now().Add(24 * time.Hour),
   Path:    "/",
}
c.SetCookie(sessionCookie)

Note: - If you need to set multiple cookies, you would call this method multiple times, passing in each cookie as a separate 'http.Cookie' object.

type FileDownloader

type FileDownloader struct {
	Dir string
}

func (*FileDownloader) Handle

func (f *FileDownloader) Handle() HandleFunc

type FileUploader

type FileUploader struct {
	FileField   string
	DstPathFunc func(*multipart.FileHeader) string
}

func (*FileUploader) Handle

func (f *FileUploader) Handle() HandleFunc

type GoTemplateEngine

type GoTemplateEngine struct {
	// T is a pointer to a compiled template object from the Go standard library's template package.
	// It stores all the parsed template files that can be executed to generate output based on dynamic data.
	T *template.Template
}

func (*GoTemplateEngine) LoadFromFS

func (g *GoTemplateEngine) LoadFromFS(fs fs.FS, patterns ...string) error

func (*GoTemplateEngine) LoadFromFiles

func (g *GoTemplateEngine) LoadFromFiles(filenames ...string) error

func (*GoTemplateEngine) LoadFromGlob

func (g *GoTemplateEngine) LoadFromGlob(pattern string) error

func (*GoTemplateEngine) Render

func (g *GoTemplateEngine) Render(ctx context.Context, templateName string, data any) ([]byte, error)

type HTTPServer

type HTTPServer struct {
	// contains filtered or unexported fields
}

HTTPServer defines the structure of an HTTP server with routing capabilities, middleware support, logging functionality, and a template engine for rendering HTML templates.

Fields:

  • router: Embeds the routing information which includes the tree of routes and handlers that the server uses to match incoming requests to their respective handlers.

  • mils []Middleware: A slice that holds the globally applied middleware. These middleware functions are executed for every request in the order they are added. They can be used to modify the http.Handler behaviour, perform actions such as logging, authentication etc.

  • log func(msg string, args ...any): A function for logging where msg is a formatted log message and args are optional arguments which may be included in the formatted output. Developers can use this to output relevant log information or to integrate third-party logging libraries.

  • templateEngine: An interface that represents the template engine used by the server to render HTML templates. This allows for dynamic HTML content generation based on data models and can be customized by the developer to use the desired templating system.

Usage: An instance of HTTPServer typically starts by configuring routes, middleware, and the template engine. Once set up, the server can handle HTTP requests, match them to their designated handlers, and generate dynamic responses. Logging is facilitated through the provided log function, enabling tracking of server activity and diagnosing issues.

func InitHTTPServer

func InitHTTPServer(opts ...HTTPServerOption) *HTTPServer

func (*HTTPServer) Connect

func (s *HTTPServer) Connect(path string, handleFunc HandleFunc)

Connect registers a new route with an associated handler function for handling HTTP CONNECT requests. The HTTP CONNECT method is utilized primarily for establishing a tunnel to a server identified by a given URI.

Parameters:

  • path string: The endpoint or route pattern where the server will listen for incoming CONNECT requests. This may include parameter placeholders that can be used to extract values from the URL during request handling.
  • handleFunc: A callback function that is invoked in response to a CONNECT request to the given path. This function has access to the request and response through a *Context, providing the necessary tools to implement the tunneling behavior or other custom logic expected on a CONNECT request.

Example usage:

s.Connect("/proxy", func(ctx *Context) {
    // Logic to establish a proxy connection.
})

Note: The use of `http.MethodConnect` ensures that only HTTP CONNECT requests are matched to this handler, facilitating the appropriate processing logic for these specialized request types, which are different from the standard GET, POST, PUT, etc., methods.

func (*HTTPServer) Delete

func (s *HTTPServer) Delete(path string, handleFunc HandleFunc)

Delete registers a new route with an associated handler function for HTTP DELETE requests. This method is used to remove a resource identified by a URI.

Parameters:

  • path string: The URL pattern that the server will listen on for incoming DELETE requests. This parameter defines the endpoint at which the handler will be called when a DELETE request matches the path.
  • handleFunc: A function that is called when a DELETE request is made to the registered path. This function should contain the logic to handle the deletion of a resource, and it is provided with a *Context object to interact with the request and response data.

Example usage:

s.Delete("/users/{id}", func(ctx *Context) {
    // Handler logic to delete a user resource with the given ID.
})

Note: Using `http.MethodDelete` in the call to registerRoute confines this handler to respond solely to DELETE requests, providing a way to define how the server handles deletions.

func (*HTTPServer) Get

func (s *HTTPServer) Get(path string, handleFunc HandleFunc)

Get registers a new route and its associated handler function for HTTP GET requests. This method is a shortcut for registering routes that should only respond to GET HTTP method, typically used for retrieving resources.

Parameters:

  • path string: The URL pattern to match against incoming requests. The route pattern can contain parameters that will be parsed from the URL and made available to the handler function during request handling.
  • handleFunc: The function to be called when a request matching the path is received. The handler function is defined to take a *Context as its only parameter, through which it can access the request data and send a response back.

Example usage:

s.Get("/home", func(ctx *Context) {
    // Handler logic for the `/home` path when an HTTP GET request is received
})

Note: The method internally calls registerRoute to add the route to the server's routing table with the method specified as `http.MethodGet`, which ensures that only GET requests are handled by the provided handler.

func (*HTTPServer) Head

func (s *HTTPServer) Head(path string, handleFunc HandleFunc)

Head registers a new route and its associated handler function for HTTP HEAD requests. This method is used to handle requests where the client is interested only in the response headers, and not the actual body of the response, which is typical behavior of a HEAD request in HTTP.

Parameters:

  • path string: The path pattern to which the route will respond. When a HEAD request to this pattern is received, the registered handler function will be executed.
  • handleFunc: The handler function that will be associated with the provided path pattern. This function will be called with a *Context parameter that contains information about the request and mechanisms to construct a response.

Example usage:

s.Head("/resource", func(ctx *Context) {
    // Handler logic to return response headers for the '/resource' path
    // without returning the actual body.
})

Note: The method utilizes the registerRoute internal function to add the route to the server's routing table specifically for the HEAD HTTP method, which ensures that only HEAD requests will trigger the execution of the provided handler function.

func (*HTTPServer) Options

func (s *HTTPServer) Options(path string, handleFunc HandleFunc)

Options registers a new route with an associated handler function for HTTP OPTIONS requests. The HTTP OPTIONS method is used to describe the communication options for the target resource.

Parameters:

  • path string: The URL pattern that the server will match against incoming OPTIONS requests. Defining the endpoint allows clients to find out which methods and operations are supported at a given URL or server.
  • handleFunc: The function to be executed when an OPTIONS request is received. It typically provides information about the HTTP methods that are available for a particular URL endpoint. The handleFunc is supplied with a *Context object to facilitate interaction with the HTTP request and response.

Example usage:

s.Options("/articles/{id}", func(ctx *Context) {
    // Handler logic to indicate supported methods like GET, POST, PUT on the article resource.
})

Note: This registration only affects OPTIONS requests due to the use of `http.MethodOptions`. It is standard practice to implement this method on a server to inform clients about the methods and content types that the server is capable of handling, thereby aiding the client's decision-making regarding further actions.

func (*HTTPServer) Patch

func (s *HTTPServer) Patch(path string, handleFunc HandleFunc)

Patch registers a new route with an associated handler function for HTTP PATCH requests. This method is generally used for making partial updates to an existing resource.

Parameters:

  • path string: The pattern of the URL that the server will match against incoming PATCH requests. The path can include variables that will be extracted from the URL and passed to the handler.
  • handleFunc: The function to execute when the server receives a PATCH request at the specified path. This function is provided with a *Context object, enabling access to request information and response functionalities.

Example usage:

s.Patch("/profile/{id}", func(ctx *Context) {
    // Handler logic to apply partial updates to a profile based on the ID in the URL.
})

Note: Registering the route with the `http.MethodPatch` constant ensures that only PATCH requests are handled by the provided function. The PATCH method is typically used to apply a partial update to a resource, and this function is where you would define how the server handles such requests.

func (*HTTPServer) Post

func (s *HTTPServer) Post(path string, handleFunc HandleFunc)

Post registers a new route and its associated handler function for handling HTTP POST requests. This method is used for routes that should accept data sent to the server, usually for the purpose of creating or updating resources.

Parameters:

  • path string: The URL pattern to match against incoming POST requests. It defines the endpoint at which the handler function will be called for incoming POST requests.
  • handleFunc: The function to be executed when a POST request is made to the specified path. It receives a *Context object that contains the request information and provides the means to write a response back to the client.

Example usage:

s.Post("/submit", func(ctx *Context) {
    // Handler logic for processing the POST request to the `/submit` path.
})

Note: The method delegates to registerRoute, internally setting the HTTP method to `http.MethodPost`. This ensures that the registered handler is invoked only for POST requests matching the specified path.

func (*HTTPServer) Put

func (s *HTTPServer) Put(path string, handleFunc HandleFunc)

Put registers a new route and its associated handler function for handling HTTP PUT requests. This method is typically used to update an existing resource or create a new resource at a specific URL.

Parameters:

  • path string: The URL pattern to which the server should listen for PUT requests. This pattern may include placeholders for dynamic segments of the URL, which can be used to pass variables to the handler function.
  • handleFunc: A callback function that will be invoked when a PUT request is made to the specified path. The function takes a *Context parameter that provides access to the request data and response writer.

Example usage:

s.Put("/items/{id}", func(ctx *Context) {
    // Handler logic for updating an item with a particular ID using a PUT request.
})

Note: By calling registerRoute and specifying `http.MethodPut`, this method ensures that the handler is specifically associated with PUT requests. If a PUT request is made on the matched path, the corresponding handler function will be executed.

func (*HTTPServer) ServeHTTP

func (s *HTTPServer) ServeHTTP(writer http.ResponseWriter, request *http.Request)

func (*HTTPServer) Start

func (s *HTTPServer) Start(addr string) error

func (*HTTPServer) Trace

func (s *HTTPServer) Trace(path string, handleFunc HandleFunc)

Trace registers a new route with an associated handler function for HTTP TRACE requests. The HTTP TRACE method is used to echo back the received request so that a client can see what (if any) changes or additions have been made by intermediate servers.

Parameters:

  • path string: The endpoint on the server that will respond to the TRACE requests. This defines the path pattern that must be matched for the handler function to be invoked.
  • handleFunc: A function that handles the TRACE request. It should process the request and typically returns the same request message in the response body. This function has a *Context object allowing access to the request details and the ability to write the response.

Example usage:

s.Trace("/echo", func(ctx *Context) {
    // Handler logic that echoes the incoming request back to the client.
})

Note: Registering this route specifically listens for HTTP TRACE requests by using `http.MethodTrace`. This is helpful for debugging purposes where the client needs to understand what headers and body are being received by the server after any possible alterations by intermediate devices.

func (*HTTPServer) Use

func (s *HTTPServer) Use(mils ...Middleware)

Use attaches the provided middlewares to the existing set of middlewares in the HTTPServer instance. If no middleware has been set yet, it initializes the middleware list with the provided ones. If there are already middlewares present in the server, it appends the new ones to the end of the middleware chain.

Middlewares are executed in the order they are added to the server, meaning that the order of middlewares can affect the request/response processing. They are commonly used to handle tasks such as request logging, authentication, input validation, error handling, etc.

Usage example:

server := &HTTPServer{}
server.Use(loggingMiddleware)
server.Use(authenticationMiddleware)

Parameters: - mils ...Middleware : One or multiple Middleware functions to add to the server's middleware chain.

Note: This method appends provided middlewares variably, allowing for zero or more middlewares to be added at once. If called with no arguments, it will simply do nothing to the current middleware chain.

func (*HTTPServer) UseRoute

func (s *HTTPServer) UseRoute(method string, path string, mils ...Middleware)

UseRoute associates a new route with the specified HTTP method and path to the server's routing system. Additionally, it allows for the chaining of middleware functions that can intercept and modify the request or response, or perform specific actions like logging, authentication, etc., before the request reaches the final handler function.

Parameters:

  • method string: The HTTP method (e.g., GET, POST, PUT, DELETE) for which the route is to be registered.
  • path string: The path pattern to be matched against the URL of incoming requests.
  • mils ...Middleware: A variadic parameter that allows passing an arbitrary number of middleware functions. These functions are executed in the order they are provided, prior to the final handler.

Usage: When registering a route, you can specify the HTTP method and path, followed by the series of middleware you wish to apply. If no final handler is provided at the time of route registration, one must be attached later for the route to be functional.

Example usage:

s.UseRoute("GET", "/articles", AuthMiddleware, LogMiddleware)

Here, `AuthMiddleware` would be used to authenticate the request, and `LogMiddleware` would log the request details. A route handler would need to be added subsequently to handle the GET requests for `/articles` path.

Note: This method is used for initial route setup and must be combined with a handler registration to create a complete, functional route. If a handler is not attached later, the route will not have any effect.

type HTTPServerOption

type HTTPServerOption func(server *HTTPServer) // Functional option for configuring an HTTPServer

HTTPServerOption defines a function type used to apply configuration options to an HTTPServer.

Each HTTPServerOption is a function that accepts a pointer to an HTTPServer and modifies it according to some configuration logic. This pattern, often called "functional options", allows for flexible, clear, and safe configurations when constructing an instance of HTTPServer. It enables the programmer to chain multiple configuration options in a declarative way when creating a new server instance or adjusting its settings.

Usage: Developers can define custom HTTPServerOption functions that set various fields or initialize certain parts of the HTTPServer. These options can then be passed to a constructor function that applies them to the server instance.

Example:

func WithTemplateEngine(engine TemplateEngine) HTTPServerOption {
  return func(server *HTTPServer) {
    server.templateEngine = engine
  }
}

func WithMiddleware(middleware ...Middleware) HTTPServerOption {
  return func(server *HTTPServer) {
    server.mils = append(server.mils, middleware...)
  }
}

// When initializing a new HTTPServer:
srv := NewHTTPServer(
  WithTemplateEngine(myTemplateEngine),
  WithMiddleware(AuthMiddleware, LoggingMiddleware),
)

func ServerWithMiddleware

func ServerWithMiddleware(mils ...Middleware) HTTPServerOption

ServerWithMiddleware takes a variadic slice of Middleware functions and returns an HTTPServerOption. This option configures a HTTPServer with the provided middlewares. Middlewares are used to intercept or otherwise modify requests and responses in an HTTP server. Middleware functions are typically used for logging, security controls, rate limiting, etc.

Example of using ServerWithMiddleware to configure an HTTPServer with middlewares:

myServer := NewHTTPServer(
    ServerWithMiddleware(loggingMiddleware, authenticationMiddleware),
)

Parameters: - mils ...Middleware : A variadic slice of Middleware functions to be applied to the server.

Returns:

  • HTTPServerOption : A function that takes an HTTPServer pointer and assigns the provided middlewares to it. This function can be applied as a configuration option when creating an HTTPServer.

func ServerWithTemplateEngine

func ServerWithTemplateEngine(templateEngine TemplateEngine) HTTPServerOption

ServerWithTemplateEngine is a configuration function that returns an HTTPServerOption. This option is used to set a specific TemplateEngine to the HTTPServer, which can then be used to render HTML templates for the client. It's useful when your server needs to deliver dynamic web pages that are generated from templates.

A TemplateEngine is an interface or a set of functionalities that processes templates with given data and produces an HTML output that the HTTP server can send to the client's web browser.

Usage example:

server := NewHTTPServer(
    ServerWithTemplateEngine(myTemplateEngine),
)

Parameters:

  • templateEngine : The template engine to be set on the HTTPServer. This parameter specifies the concrete implementation of a template engine that the server will use for rendering templates.

Returns:

  • HTTPServerOption : A function that configures the server with the specified template engine. When applied as an option to the server, it assigns the 'templateEngine' to the server's internal field for later use.

type HandleFunc

type HandleFunc func(ctx *Context) // Type signature for request handling functions within the framework

HandleFunc defines the function signature for an HTTP request handler specific to your web framework.

This type represents a function that takes a pointer to a Context object as its argument and does not return any value. The Context object typically encapsulates all the information about the current HTTP request, including the request itself, response writer, path parameters, query parameters, and any other metadata or utilities needed to process the request.

Usage: A HandleFunc is intended to be used as a callback for specific routes to handle incoming HTTP requests. Each route will have an associated HandleFunc that will be executed when the route is matched.

Example:

func HelloWorldHandler(ctx *Context) {
  ctx.ResponseWriter.Write([]byte("Hello, World!"))
}

// Registering the handler with a route:
server.registerRoute("GET", "/hello", HelloWorldHandler)

type Middleware

type Middleware func(next HandleFunc) HandleFunc

Middleware represents a function type in Go that defines the structure of a middleware function. In the context of web servers or other request-handling applications, middleware is used to process requests before reaching the final request handler, allowing for pre-processing like authentication, logging, or any other operation that should be performed before or after the main processing of a request.

The type is defined as a function that takes one HandleFunc as its parameter (often referred to as 'next') and returns another HandleFunc. The HandleFunc inside the parentheses is the next function in the chain that the middleware will call, while the HandleFunc being returned is the modified or "wrapped" version of that function.

A typical middleware will perform some actions, then call 'next' to pass control to the subsequent middleware or the final handler, potentially perform some actions after 'next' has returned, and finally return the result of 'next'. By doing so, it forms a chain of middleware functions through which the request flows.

The Middleware type is designed to be flexible and composable, making the construction of an ordered sequence of middleware functions straightforward and modular.

Parameters:

  • 'next': The HandleFunc to wrap with additional behavior. This is the function that would normally handle the request or be the next middleware in line.

Return Value: - A HandleFunc that represents the result of adding the middleware's behavior to the 'next' function.

Usage:

  • Middleware functions are typically used with a router or a server to handle HTTP requests.
  • They are chained together so that a request goes through a series of middleware before finally being handled by the main processing function.

Example: - To write a logging middleware that logs each request:

func loggingMiddleware(next HandleFunc) HandleFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // Log the request details
        log.Printf("Request received: %s %s", r.Method, r.URL.Path)
        // Call the next middleware/handler
        next(w, r)
    }
}

// Then this middleware can be used like so:
http.Handle("/", loggingMiddleware(finalHandler))

Considerations:

  • When designing middleware, one should ensure that no necessary 'next' handlers are skipped inadvertently. Unless it's intentional (e.g., an authorization middleware stopping unauthorized requests), a middleware should usually call 'next'.
  • Be careful with error handling in middleware. Decide whether to handle and log errors within the middleware itself or pass them along to be handled by other mechanism.
  • Middleware functions should avoid altering the request unless it is part of its clear responsibility, such as setting context values or modifying headers that pertain to middleware-specific functionality.

type Server

type Server interface {
	http.Handler             // Inherited ServeHTTP method for handling requests
	Start(addr string) error // Method to start the server on a given address
	// contains filtered or unexported methods
}

Server defines the interface for an HTTP server that can handle requests and be started on a specified address. It extends the http.Handler interface of the net/http package, which requires a ServeHTTP method to serve HTTP requests. In addition to handling HTTP requests, the server can register routes with associated handlers and middleware, and be started on a network address.

Methods:

  • Start(addr string) error: Starts the server listening on the specified network address (addr). If the server fails to start, it returns an error.

  • registerRoute(method string, path string, handleFunc, mils ...Middleware): Registers a new route with a specific HTTP method and path. If provided, handleFunc becomes the main function to handle matched requests; mils represents variadic middleware functions which will be processed before the handleFunc upon route matching.

Note:

  • The registerRoute method is generally not exposed and is intended for internal use by implementations of the Server interface. Implementations should ensure that routes are properly registered and middleware is correctly applied within this method.

Example: An implementation of the Server interface could manage its own routing table and middleware stack, allowing for modular and testable server designs. It would typically be used within an application like so:

func main() {
  srv := NewMyHTTPServer()  // MyHTTPServer implements the Server interface
  srv.registerRoute("GET", "/", HomePageHandler, LoggingMiddleware)
  err := srv.Start(":8080")
  if err != nil {
    log.Fatalf("Failed to start server: %v", err)
  }
}

type StaticResourceHandler

type StaticResourceHandler struct {
	// contains filtered or unexported fields
}

func InitStaticResourceHandler

func InitStaticResourceHandler(dir string, opts ...StaticResourceHandlerOption) (*StaticResourceHandler, error)

func (*StaticResourceHandler) Handle

func (s *StaticResourceHandler) Handle(ctx *Context)

type StaticResourceHandlerOption

type StaticResourceHandlerOption func(handler *StaticResourceHandler)

func StaticWithCache

func StaticWithCache(c *lru.Cache) StaticResourceHandlerOption

func StaticWithExtension

func StaticWithExtension(extMap map[string]string) StaticResourceHandlerOption

func StaticWithMaxFileSize

func StaticWithMaxFileSize(maxSize int) StaticResourceHandlerOption

type StringValue

type StringValue struct {
	// contains filtered or unexported fields
}

StringValue is a structure designed to encapsulate a string value and any associated error that may arise during the retrieval of the value. It is commonly used in functions that perform operations which may fail, such as parsing, reading from a file, or extracting values from a request in web applications. By combining both the value and the error in a single struct, it simplifies error handling and value passing between functions.

Fields:

  • 'val': This field holds the string value that is retrieved by the operation. For example, when extracting a value from a form or parsing a string, 'val' will hold the result. If the operation to retrieve the value fails (for instance, if a key doesn't exist or a parse error occurs), 'val' will typically be set to an empty string.

  • 'err': This field is used to hold any error that occurred during the operation. The presence of a non-nil error typically indicates that something went wrong during the value retrieval process. It allows the caller to distinguish between a successful operation (where 'err' is nil) and unsuccessful ones (where 'err' is not nil). The specific error stored in 'err' can provide additional context about what went wrong, enabling the caller to take appropriate actions, such as logging the error or returning an error response in a web application.

Usage:

  • The 'StringValue' struct is useful in scenarios where a function needs to return both a value and an error status, so the caller can easily handle errors and control flow. It is particularly helpful in HTTP handler functions where error handling is integral to the proper functioning of the server.

Example:

  • Suppose there is a web server with a function that reads a configuration value labeled "timeout" from a file or an environment variable. If the retrieval is successful, 'val' will contain the timeout string, and 'err' will be nil. If the retrieval fails (for example, if the "timeout" label doesn't exist), then 'err' will contain the error message, and 'val' will be an empty string. This struct helps the caller response appropriately based on whether an error occurred or not.

Considerations:

  • When using 'StringValue' in code, it is good practice to always check the 'err' field before using the 'val' field. This avoids any surprises from using invalid values.
  • The design of 'StringValue' is such that it obviates the need for functions to return separate values for the string retrieved and an error. Instead, both pieces of information can be returned together in a more streamlined manner.

func (*StringValue) AsFloat64

func (s *StringValue) AsFloat64() (float64, error)

AsFloat64 converts the string value encapsulated within the StringValue struct to a float64 type. This operation is essential in situations where the string value is expected to contain a floating-point number that will be used in complex calculations or any context where precise decimal values are necessary, such as financial computations or scientific measurements.

The method follows a clear two-step conversion process:

  1. It first checks for the presence of an error in the 'err' field of the StringValue struct. If an error is already associated with the value, the method precludes any conversion attempt and immediately returns a zero value (0.0) and the stored error, preserving the integrity of the error handling flow.

  2. If no error is found (i.e., 'err' is nil), the method utilizes the strconv.ParseFloat function to attempt the conversion of the string value to a float64. The function parameter '64' specifies that the conversion should result in a floating-point number that adheres to a 64-bit IEEE 754 representation. This conversion is capable of handling both integer values and floating-point strings, including those with scientific notation.

    If the conversion is conducted successfully, the parsed float64 value is returned alongside a nil error to indicate a successful operation. However, if strconv.ParseFloat encounters any issues—such as if the string contains characters inappropriate for a numeric value, or if the number is outside the range representable by a float64—the method will instead yield a zero value (0.0) with the corresponding error.

Parameters: - None. The method operates solely on the fields contained within the invoked StringValue struct instance.

Return Values: - A float64 value representing the successfully converted string or 0.0 in the event of an error. - An error object that either carries an existing error from 'err' or a newly encountered error in conversion.

Usage:

  • Users of this method should handle the returned error prior to using the numeric result to ensure that no conversion error has taken place and the result is indeed a valid and accurate floating-point number.

Example: - If a 'StringValue' instance named 'priceString' comes from a reliable function that parses a price value:

priceString := parsePriceValueFromInput()
price, err := priceString.AsFloat64()
if err != nil {
    // Error handling logic such as logging the error or prompting the user to provide a valid numeric value.
} else {
    // The price variable is now appropriately typed as a float64 and ready for financial calculations.
}

Considerations:

  • The float64 type follows IEEE 754 standards and is the set choice for all floating-point operations within Go, offering a double-precision floating-point format which is fairly suited for a wide range of numerical tasks.
  • Ensure that the source string is supposed to represent a floating-point value and that it is formatted correctly. Proper validation or sanitization might be essential if the input is obtained from external or untrusted sources.

func (*StringValue) AsInt64

func (s *StringValue) AsInt64() (int64, error)

AsInt64 attempts to convert the value held in the StringValue struct to an int64 type. This method is particularly useful when the string value is expected to hold a numeric value that needs to be used in a context where integer types are required (e.g., calculations, database operations, etc.).

This method performs a two-step process:

  1. It checks if the err field of the StringValue receiver is not nil, which implies that an error occurred in acquiring or processing the original string value. If an error is present, the method immediately returns 0 and the error, propagating the original error without attempting to convert the value.
  2. If there is no error associated with the string value (i.e., err is nil), the method attempts to parse the string as an int64 base 10 number with the strconv.ParseInt function. If the parsing succeeds, it returns the resulting int64 value and a nil error. If parsing fails, it returns 0 and the parsing error that occurred.

Parameters: - None. The method operates on the StringValue structs internal state.

Return Value:

  • The first return value is the int64 result of the parsing operation. It is set to 0 if there is an error.
  • The second return value is the error encountered during the conversion process. It will contain any error that may have previously been present in the StringValue struct or any error that occurs during the parsing with strconv.ParseInt.

Usage:

  • It is essential to always handle the error return value to ensure that the int64 conversion was successful. Do not use the numeric value if the error is non-nil, as it would be incorrect or undefined.

Example:

  • Suppose we have a StringValue struct that is created as the result of another function that reads a stringifies integer from user input or external data source:

    value := otherFunctionThatReturnsStringValue() number, err := value.AsInt64() if err != nil { // handle the error (e.g., log the error or inform the user of a bad input) } else { // use the number for further processing }

Considerations:

  • This method allows for a clean and efficient interpretation of string data when an integer is expected. Doing so can simplify error handling by centralizing the conversion logic and error checking.
  • The strconv.ParseInt function is configured to interpret the string as a base 10 integer within the int64 range. This corresponds to the range of -9223372036854775808 to 9223372036854775807.
  • Make sure that the source string is appropriately validated or sanitized if coming from an untrusted source before attempting the conversion to mitigate any risks such as injection attacks or data corruption.

func (*StringValue) AsUint64

func (s *StringValue) AsUint64() (uint64, error)

AsUint64 attempts to convert the string value within the StringValue struct to an uint64 type. This method is crucial when the string is expected to represent an unsigned numeric value that must be processed in environments or calculations that specifically require unsigned integers.

The method involves the following steps:

  1. First, it verifies whether the 'err' field in the StringValue struct is not nil, indicating an error was encountered during the prior retrieval or conversion of the string value. Should an error be present, the method exits early, returning 0 for the numeric value and passing the error forward.
  2. If the 'err' field is nil, signaling no previous error, the method proceeds to parse the string value to an uint64 using the strconv.ParseUint function. This function is instructed to interpret the string value as a base 10 number. The second argument (10) specifies the number base (decimal in this case), and the third argument (64) specifies that the conversion should fit into a 64-bit unsigned integer format.
  3. If the conversion is successful, the method outputs the parsed uint64 value and a nil error. If the conversion fails (e.g., if the string contains non-numeric characters or represents a number outside the uint64 range), it instead returns 0 and the error produced by strconv.ParseUint.

Parameters: - There are no parameters taken by this method, as it operates on the 'StringValue' struct instance it is called upon.

Return Value: - An uint64 type value representing the converted string if successful. - An error indicating the conversion failed or an error was present already in the StringValue struct's 'err' field.

Usage:

  • The caller should always evaluate the error returned by this function before utilizing the numeric value, to ensure the conversion occurred correctly and the result is valid and reliable for further use.

Example: - Imagine a situation where the 'StringValue' instance 'numericString' was created by parsing a user-provided configuration value:

numericString := GetStringFromConfig("max_users")
maxValue, err := numericString.AsUint64()
if err != nil {
    // Handle the error appropriately (e.g., fallback to default value, logging, or user notification)
} else {
    // The maxValue is now safe to use for setting the maximum users allowed
}

Considerations:

  • This method assists in preventing the proliferation of error handling logic scattered throughout codebases by encapsulating both the value and potential errors within a single, self-contained struct.
  • The uint64 data type can represent integers from 0 to 18,446,744,073,709,551,615. Ensure the source string is meant to fit within this range.
  • Additional validation might be required for the initial string value if it comes from external or user inputs to prevent errors during conversion.

type TemplateEngine

type TemplateEngine interface {
	// Render takes the name of a template and the data object to be used in rendering, and returns the
	// rendered template as a slice of bytes, or an error if the rendering could not be completed. This
	// method abstracts the rendering logic, enabling different templating systems to be integrated into
	// the application as needed.
	Render(ctx context.Context, templateName string, data any) ([]byte, error)
}

Directories

Path Synopsis
internal
middlewares

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL