Categorygithub.com/nixpare/server/v2
modulepackage
2.11.2
Repository: https://github.com/nixpare/server.git
Documentation: pkg.go.dev

# README

Nix Server (v2)

Overview

This package provides an HTTP/S server that can be easily configured for serving static files in few lines of code, but also scaled to have a server that can handle multiple domains and subdomains, with their logic for every incoming request, backgound tasks and event logging.


Package structure

The package mainly relies on the Server object, which listens on a specific port and forwards every connection to the inner handler.

Basic Implementation

For a basic Server configuration that serves every connection with the content of the public folder located in the working directory, here is how to configure it:

package main

import (
	"os"
	"os/signal"

	"github.com/nixpare/server/v2"
)

func main() {
	// Create a new server on port 8080, not secure
	// (that means using http and not https) and empty
	// path (so the path is the working directory)
	srv, err := server.NewServer(8080, false, "")
	if err != nil {
		panic(err)
	}

	// Register a default route that serves every files inside
	// the /public folder
	srv.RegisterDefaultRoute("Default", server.SubdomainConfig{})
	// The server starts listening on the port
	srv.Start()

	// Listens for a Control-C
	exitC := make(chan os.Signal)
	signal.Notify(exitC, os.Interrupt)
	<- exitC
	// Stops the server after the Control-C
	srv.Stop()
}

Advanced Implementation

For a more anvanced implementation we need a Router that will manage every server listening on different ports and domains, along with a TaskManager that can be used for creating panic-safe goroutines running in the background.

So we first need a router

// new router with path set to the working directory and log output
// equal to the stdout
router, _ := server.NewRouter("", nil)

that will be used to create the servers (we will only implement one)

srv, _ := router.NewServer(443, true, server.Certificate{
	CertPemPath: "path/to/fullchain_key.pem",
	KeyPemPath: "path/to/private_key.pem",
}/*, other certificates concatenated ...*/)

then on each server we can register multiple domains and subdmains

mainDomain := srv.RegisterDomain("My Domain", "mydomain.com")
localDomain := srv.RegisterDomain("Localhost Connections", "localhost")

// This registers the subdomain sub.mydomain.com
// serveFunction will be explained below
mainDomain.RegisterSubdomain("sub", server.SubdomainConfig{
	ServeF: serveFunction,
	Website: server.Website{
		Name: "My Website",
		Dir: "Custom Dir holding files",
		PageHeaders: map[string][][2]string{
			"/": {
				{"header_name_1", "value for index page"},
				{"header_name_2", "other value for index page"}
			},
			"/page": {{"header_name", "value for page page"}},
		} // The PageHeaders field can be seen as an object that maps
		  // a string to a series of string couples, each rapresenting
		  // the key-value pair for an http header
	}
})

localDomain.RegisterSubdomain(...)

The serving function - Route

To manage every connection with your own logic, the only structures you need are the Route and Website ones, and in order to let the server know which function to call you have to provide one in the ServeF field of the SubdomainConfig. The function must have a signature as descrived by the type server.ServeFunction -> func(route *server.Route), that is a simple function taking in input just the Route. This structure holds everything you need for a web request:

  • functions to serve content (ServeFile, ServeData, Error)
  • functions to manage cookies (SetCookie, DeleteCookie, DecodeCookie)
  • other functions
  • reference to the underlying http.ResponseWriter and *http.Request for using any standard http function from the stardard library (or even third party ones that need those type of structures)

The TaskManager

It can used to manage background functions and processes running in background, with panic protection to avoid the crash of the entire program and the possibility to listen for the router shutdown in order to interrupt any sensitive procedure. This functions so have a lifecycle composed of:

  • a startup function that is ran when the task is started for the first time (unless it's later stopped)
  • a cleaup function that is run when the task is stopped
  • an exec function that can be ran manually or by the task timer

The task timer determines if and how ofter the task exec function should be called and can be changed at any time after creation

Other utility functions

Inside the utility.go file of the package there are some useful functions, but mostly I highlight these two of them:

  • RandStr, which generates a random string with the given length populated with the chosen sets of characters (see CharSet constants)
  • PanicToErr, which can be used to call any function returning an error and automatically wrapping them in a panic-safe environment that converts the panic into a simple error with a helpful stack trace for the panic (or just returns the simple error of the function)
func myFunction(arg string) error {
  if arg == "" {
  	panic("Empty arg")
  }
  return errors.New(arg)
}
myArg = "argument"
err := PanicToErr(func() error { return myFunction(myArg) })
// err.Error() is not nil both when the function returned an error
// or a panic has occurred, but:
//  - in the first case, only the err.Err field will be set
//  - in the second case, both the err.PanicErr and err.Stack will be set
if err.Error() != nil {
  // ...
}

# Packages

No description provided by the author
No description provided by the author

# Functions

DecodeCookie decodes a previously set cookie with the given name using the method route.SetCookie and returns the saved value.
DecodeCookiePerm decodes a previously set cookie with the given name using the method route.SetCookiePerm and returns the saved value.
No description provided by the author
No description provided by the author
GenerateHashString generate a hash with sha256 from data.
No description provided by the author
NewServer creates a new server.
No description provided by the author
No description provided by the author
NewRouter returns a new Router ready to be set up.
No description provided by the author
No description provided by the author
RandStr generates a random string with the given length.
ReadJSON unmarshals the response body and returns the value.
No description provided by the author
No description provided by the author
No description provided by the author

# Constants

Latin letters from A to z (Uppercase and Lowercase).
Latin letters from a to z (Lowercase).
Combination of NUM and ALPHA_LOW.
Combination of NUM and ALPHA.
Combines ALPHA_LOW with this special character: !?+*-_=.&%$€#@.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Digits from 0 to 9.
TASK_TIMER_1_HOUR determines a Task execution interval of 1 hour.
TASK_TIMER_1_MINUTE determines a Task execution interval of 1 minute.
TASK_TIMER_10_MINUTES determines a Task execution interval of 10 minutes.
TASK_TIMER_10_SECONDS determines a Task execution interval of 10 seconds.
TASK_TIMER_30_MINUTES determines a Task execution interval of 30 minutes.
TASK_TIMER_INACTIVE deactivates the Task automatic execution.

# Variables

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
TimeFormat defines which timestamp to use with the logs.
No description provided by the author

# Structs

Certificate rapresents a standard PEM certicate composed of a full chain public key and a private key.
Domain rapresents a website domain with all its subdomains.
HTTPServer is a single HTTP server listening on a TCP port.
No description provided by the author
No description provided by the author
ResponseWriter is just a wrapper for the standard http.ResponseWriter interface, the only difference is that it keeps track of the bytes written and the status code, so that can be logged.
Route wraps the incoming HTTP connection and provides simple and commonly use HTTP functions, some coming also from the standard library.
Router is the main element of this package and is used to manage all the servers and the background tasks.
Subdomain rapresents a particular subdomain in a domain with all the logic.
SubdomainConfig is used to create a Subdomain.
Task is composed of a name set upon creation and of 3 functions necessary of the correct execution of a kind of program.
TaskManager is a component of the Router that controls the execution of external processes and tasks registered by the user.
No description provided by the author
No description provided by the author
Website is used in a subdomain to serve content with its logic, in combination with a ServeFunction and (optionally) a pair of InitCloseFunction.

# Type aliases

BeforeServeFunction defines the type of the function executed whenever a connection is received in the domain, even before any error handling (like domain and subdomain check), so every field inside Route is ready.
CharSet groups the possible output of the function RandStr.
No description provided by the author
InitCloseFunction defines the type of the function executed when a new subdomain is created or removed, usually when the relative server is started or stopped.
No description provided by the author
ServeFunction defines the type of the function that is executed every time a connection is directed to the relative website / subdomain.
TaskFunc is the executable part of the program.
TaskInitFunc is called when creating a task and is provided by the user.
TaskTimer tells the TaskManager how often a Task should be executed.