goapi

package module
v0.0.0-...-98ab9ba Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2024 License: MIT Imports: 11 Imported by: 0

README

GoAPI

A Fast and Easy-to-use Web Framework for Building APIs in Go

tests status Bring Them Home


Documentation: https://github.com/hvuhsg/GoAPI/README.md

Source Code: https://github.com/hvuhsg/GoAPI


GoAPI is a web framework written in Go that is inspired by FastAPI. It allows you to quickly build and deploy RESTful APIs with minimal effort. The framework comes with built-in validators that can be used to validate and auto-build the API schema with OpenAPI format (version 3). This means you can focus on the main logic of your application while the framework handles the validation and API documentation generation.

The key features are:

  • automatic docs ---->
  • extensible validators system ---->
  • high level syntax ---->
  • middlewares support ---->
  • native handlers support ---->
  • SSL/TLS support ---->
  • ngrok tunnel built in ---->

Quick Start

Install

To install GoAPI, you need to have Go version 1.13 or higher installed on your system. Once you have installed Go, you can use the following command to install GoAPI:

go get github.com/hvuhsg/GoAPI
Usage

To use GoAPI, you need to import it in your Go code and create a new instance of the goapi.App object:

package main

import "github.com/hvuhsg/goapi"

func main() {
	app := goapi.GoAPI("small", "1.0v")
}

Once you have created the app instance, you can add routes to it by calling the Path() method and specifying the route path. You can also set the HTTP methods that the route supports using the Methods() method. Here is an example of a route that support GET method:

package main

import (
	"github.com/hvuhsg/goapi"
	"github.com/hvuhsg/goapi/request"
	"github.com/hvuhsg/goapi/responses"
	"github.com/hvuhsg/goapi/validators"
)

func main() {
	app := goapi.GoAPI("small", "1.0v")

	echo := app.Path("/echo")
	echo.Methods(goapi.GET)
	echo.Description("echo a back")
	echo.Parameter("a", goapi.QUERY, validators.VRequired{}, validators.VIsInt{})
	echo.Action(func(request *request.Request) responses.Response {
		return responses.NewJSONResponse(responses.Json{"a": request.GetInt("a")}, 200)
	})

	app.Run("127.0.0.1", 8080)
}

In the above example, we have created a route at /echo that supports GET method. We have also added a description for the route and specified that it expects an integer parameter called "a". Finally, we have specified the action that should be performed when the route is accessed. In this case, we are returning a JSON object that contains a "a" key with the value of a as an integer.

You can add as many routes as you like to the app instance, and each route can have its own unique set of parameters and validators.

Examples

To help you get started with using GoAPI, we have provided some examples in the examples directory of the repository. These examples demonstrate various use cases of the framework and how to use its features.

The examples included are:

  • smallest The smallest example of ready to run api.
  • math_api Simple use of methods, parameters and validators.
  • external_handler Use of external handler (FileServer) int the app.
  • tls Running the app with HTTPS support.
  • ngrok_tunnel Run your app over ngrok tunnel without any external dependencies.

To run the examples, navigate to the examples directory and run the following command:

go run <example_name>/main.go

This will start the example server 127.0.0.1:8080 and you can visit the example endpoints in your web browser or via curl. To see all of the endpoints tou can visit 127.0.0.1:8080/docs to see the auto generated interactive docs.

Feel free to use these examples as a starting point for your own projects and modify them as needed.

Validation

GoAPI comes with built-in validators that can be used to validate input data automatically. In the above example, we used the VIsInt validator to ensure that the "timestamp" parameter is an integer. We also used the VRange validator to ensure that the "a" and "b" parameters falls within a specified range.

If the input data fails validation, the framework will automatically return an error to the client. This means you can focus on the main logic of your application, and the framework will handle the validation for you.

Here is a validator for example

See validator
// VRange implementaion for refernce
type VRange struct {
	Min float64
	Max float64
}

func (v VRange) UpdateOpenAPISchema(schema *openapi3.Schema) {
	schema.Min = &v.Min
	schema.Max = &v.Max
}
func (v VRange) Validate(r *request.Request, paramName string) error {
	vr := VIsFloat{}
	err := vr.Validate(r, paramName)
	if err != nil {
		return err
	}

	fVal := r.GetFloat(paramName)

	if fVal < v.Min || fVal > v.Max {
		return fmt.Errorf("parameter %s must be between %f and %f", paramName, v.Min, v.Max)
	}

	return nil
}

Middlewares

GoAPI supports middlewares, middlewares can be defind in the app level or in the view level, middlewares in the app level are applied to all views.

here is an example for logging middleware, that logs requests in the format that nginx uses.

See middleware
type LoggingMiddleware struct{}

func (LoggingMiddleware) Apply(next AppHandler) AppHandler {
	return func(request *request.Request) responses.Response {
		response := next(request)

		scheme := "http"
		if request.HTTPRequest.TLS != nil {
			scheme = "https"
		}
		fullURL := fmt.Sprintf("%s://%s%s", scheme, request.HTTPRequest.Host, request.HTTPRequest.URL.String())

		method := request.HTTPRequest.Method
		path := request.HTTPRequest.URL.Path
		responseSize := len(response.ToBytes())
		remoteAddr := request.HTTPRequest.RemoteAddr
		date := time.Now().Format("2006-01-02 15:04:05")
		userAgent := request.HTTPRequest.UserAgent()
		statusCode := response.StatusCode()

		log.Printf("%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\"\n", remoteAddr, date, method, path, request.HTTPRequest.Proto, statusCode, responseSize, fullURL, userAgent)
		return response
	}
}

To apply middlewares simply pass it to the Middlewares method for the app or for the view.

package main

import (
	"net/http"

	"github.com/hvuhsg/goapi"
	"github.com/hvuhsg/goapi/middlewares"
)

func main() {
	app := goapi.GoAPI("external handler", "1.0v")
	app.Middlewares(middlewares.LoggingMiddleware{})
}

Native handlers

To allow the usage of native handlers we added a simple way to include them in the app, simply pass the native Handler into the Include method of the app.

Note that native handlers will not be shown in the automatic docs, and currently will not be affected by the middlewares.

here is an example:

package main

import (
	"net/http"

	"github.com/hvuhsg/goapi"
)

func main() {
	app := goapi.GoAPI("external handler", "1.0v")

	// Serve files from GoAPI app using the Include method that allow us to include external handlers in the app
	app.Include("/", http.FileServer(http.Dir(".")))

	app.Run("127.0.0.1", 8080)
}

API Documentation

GoAPI can automatically generate API documentation in OpenAPI format (version 3). This makes it easy to share your API with others and integrate it with other tools that support OpenAPI.

To generate the API documentation, you can simply visit the "/docs" endpoint in your web browser. This will display a user-friendly interface that allows you to view the API schema and test the API endpoints. For the JSON schema you can visit "/openapi.json".

Swagger UI Swagger route open

HTTPS Support

GoAPI can also serve the api over https, this is not recommanded for production. We recommand using Nginx or other types of reverse proxy to handle the SSL/TLS security.

To run the application over TLS just use the RunTLS method of the app.

package main

import (
	"github.com/hvuhsg/goapi"
	"github.com/hvuhsg/goapi/request"
	"github.com/hvuhsg/goapi/responses"
)

func main() {
	app := goapi.GoAPI("TLS example", "1.0v")

	root := app.Path("/")
	root.Methods(goapi.GET)
	root.Description("simple route")
	root.Action(func(request *request.Request) responses.Response {
		return responses.NewHTMLResponse("<h1>HTML Over HTTPS</h1>", 200)
	})

	app.RunTLS("127.0.0.1", 8080, "./server.crt", "./server.key")
}

Ngrok Tunnel

GoAPI support seamless and simple use of ngrok tunnels during the development of the server.

Code example
package main

import (
	"log"
	"os"

	"github.com/hvuhsg/goapi"
	"github.com/hvuhsg/goapi/request"
	"github.com/hvuhsg/goapi/responses"
)

func main() {
	app := goapi.GoAPI("ngrok tunnel", "1.0v")

	echo := app.Path("/")
	echo.Methods(goapi.GET)
	echo.Description("home page")
	echo.Action(func(request *request.Request) responses.Response {
		return responses.NewHTMLResponse("<h1>Served over ngrok tunnel</h1>", 200)
	})

	ngrokToken := os.Getenv("NGROK_TOKEN")
	if ngrokToken == "" {
		log.Println("Enviroment variable NGROK_TOKEN is required")
		os.Exit(1)
	}

	app.RunNgrok(ngrokToken)
}

Documentation

Index

Constants

View Source
const (
	PATH   = "path"
	QUERY  = "query"
	HEADER = "header"
	COOKIE = "COOKIE"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type APISecurity

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

func (APISecurity) GetName

func (APISecurity) GetName() string

func (APISecurity) GetScopes

func (APISecurity) GetScopes() []string

func (*APISecurity) IsAuthenticated

func (sec *APISecurity) IsAuthenticated(r *request.Request) bool

type App

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

App represents the main application.

func GoAPI

func GoAPI(title string, version string) *App

GoAPI creates a new instance of the App.

func (*App) Contact

func (a *App) Contact(name string, url string, email string)

Contact sets the application's contact information.

func (*App) Description

func (a *App) Description(description string)

Description sets the application description.

func (*App) Include

func (a *App) Include(path string, handler http.Handler)

Serve external handler under path

func (*App) License

func (a *App) License(name string, url string)

License sets the URL for the application's license. url is optional you can pass empty string.

func (*App) Middlewares

func (a *App) Middlewares(middlewares ...middlewares.Middleware)

Add middlewares to all routes

func (*App) OpenapiDocsURL

func (a *App) OpenapiDocsURL(docsUrl string)

OpenapiDocsURL sets the URL path for the OpenAPI documentation. default to "/openapi.json".

func (*App) OpenapiSchemaURL

func (a *App) OpenapiSchemaURL(schemaUrl string)

OpenapiSchemaURL sets the URL path for the OpenAPI schema. default to "/docs"

func (*App) OptionalSecurity

func (a *App) OptionalSecurity()

Make security optional

func (*App) Path

func (a *App) Path(path string) *View

Path creates a new View for the given URL path and adds it to the App.

func (*App) Run

func (a *App) Run(host string, port int) error

Run starts the application and listens for incoming requests over HTTP.

func (*App) RunNgrok

func (a *App) RunNgrok(authtoken string) error

Use ngrok tunnel for development

func (*App) RunTLS

func (a *App) RunTLS(host string, port int, certFile string, keyFile string) error

Run starts the application and listens for incoming requests over HTTPS. This method will make the server to only support https requests, to support http and https connections do the following.

Run the app with without tls in a gorouting, and then run the app with TLS. NOTE: you can't use the same port for both, the known port for http is 80 and for https is 443.

func (*App) Security

func (a *App) Security(securiyProvider SecurityProvider)

Add security provider

func (*App) Tag

func (a *App) Tag(name string, description string)

Tag add new tag information, used in the automatic docs. can be called multiple times for multiple tags.

func (*App) TermOfServiceURL

func (a *App) TermOfServiceURL(termOfServiceURL string)

TermOfServiceURL sets the URL for the application's terms of service.

type AppHandler

type AppHandler func(request *request.Request) responses.Response

type Parameter

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

func NewParameter

func NewParameter(name string, in string, validators []validators.Validator) Parameter

type SecurityProvider

type SecurityProvider interface {
	GetName() string
	GetScopes() []string
	IsAuthenticated(*request.Request) bool
}

type View

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

func NewView

func NewView(path string) *View

func (*View) Action

func (v *View) Action(r AppHandler)

func (*View) Deprecated

func (v *View) Deprecated() *View

Mark view as deprecated

func (*View) Description

func (v *View) Description(description string) *View

func (*View) Methods

func (v *View) Methods(methods ...string) *View

func (*View) Middlewares

func (v *View) Middlewares(middlewares ...middlewares.Middleware)

func (*View) Parameter

func (v *View) Parameter(paramName string, in string, validators ...validators.Validator) *View

func (*View) Tags

func (v *View) Tags(tags ...string) *View

Jump to

Keyboard shortcuts

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