"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > How to Write APIs Like a Pro in Go with GopherLight

How to Write APIs Like a Pro in Go with GopherLight

Published on 2024-11-18
Browse:922

How to Write APIs Like a Pro in Go with GopherLight

Docs

GopherLIght

Hey folks, first I would like to thank you for choosing to use our project. Even though he is small, we did it with great enthusiasm! To start using it you first have to have go installed, let's assume you already have it. Then install the main modules of the framework, which are req and router

go get github.com/BrunoCiccarino/GopherLight/router
go get github.com/BrunoCiccarino/GopherLight/req

Already downloaded? Phew! Now we can make our first hello world.

package main

import (
    "fmt"
    "github.com/BrunoCiccarino/GopherLight/router"
    "github.com/BrunoCiccarino/GopherLight/req"
)


func main() {
    app := router.NewApp()

    // Define a route that responds to a GET request at "/hello".
    app.Get("/hello", func(r *req.Request, w *req.Response) {
        w.Send("Hello, World!")
    })

    fmt.Println("Server listening on port 3333")
    app.Listen(":3333")
}

Pretty simple, right? And there’s way more we can do with GopherLight. Keep reading for a full breakdown of HTTP methods and our Request and Response tools.

Supported HTTP Methods
Here’s the list of HTTP methods you can use with router.App. Each of these allows you to set up routes to handle different types of requests. Let’s dive in!

GET

  • Usage: app.Get(path, handler)

Retrieves data without modifying anything.
Example: Fetching a list of items or reading user details.

POST

  • Usage: app.Post(path, handler)

Sends data to create a new resource.
Example: Submitting a form or adding a new item to a list.

PUT

Usage: app.Put(path, handler)

Updates or replaces a resource. It’s an “overwrite” action.
Example: Updating a full user profile.

DELETE

Usage: app.Delete(path, handler)

Deletes a resource.
Example: Removing a user or deleting a post.

PATCH

Usage: app.Patch(path, handler)

Partially updates a resource without replacing everything.
Example: Updating just the email on a user profile.

OPTIONS

Usage: app.Options(path, handler)

Returns allowed HTTP methods for a URL, mainly for CORS preflight requests.

HEAD

Usage: app.Head(path, handler)

Like GET, but no response body. Use it to check if a resource exists.

CONNECT and TRACE

Usage: app.Connect(path, handler), app.Trace(path, handler)

Advanced methods: CONNECT sets up a tunnel (for SSL), and TRACE is for debugging, echoing back the request.

Working with req.Request and req.Response

Now that you’ve seen the routes, let’s talk about the Request and Response objects, your go-to helpers for handling incoming requests and sending responses.

Request

Each request handler gets a Request object loaded with info on the incoming request. Here’s what you can do with it:

  • Query Parameters: Get query parameters with .QueryParam("key").
  • Headers: Access headers using .Header("key").
  • Body as String: Grab the request body with .BodyAsString().

Example:

app.Get("/greet", func(r *req.Request, w *req.Response) {
    name := r.QueryParam("name")
    if name == "" {
        name = "stranger"
    }
    w.Send("Hello, "   name   "!")
})

Response

The Response object helps you send a reply back to the client. Here's what you can do:

  • Send Text: .Send(data string) writes plain text back.
  • Set Status: .Status(code) sets the HTTP status.
  • Send JSON: .JSON(data) serializes a Go object to JSON and sends it.
  • Handle Errors: .JSONError(message) sends a JSON-formatted error response.

Example:

app.Get("/user", func(r *req.Request, w *req.Response) {
    user := map[string]string{"name": "Gopher", "language": "Go"}
    w.JSON(user)
})

Middlewares

We’ve got a batch of middlewares ready for you to add some serious functionality to your Go web app. Each of these middlewares brings its own magic—security, logging, timeouts, and more! Let’s break them down one by one. ?

Authentication Middleware (JWT)

Our AuthMiddleware helps protect your routes with JSON Web Tokens (JWT). It’s flexible, letting you customize the secret key, error handling, and token extraction method.

Setup
To get started, configure your JWT settings using JWTConfig:

  • SecretKey: The secret key for signing JWTs.
  • SigningMethod: The JWT signing algorithm.
  • ErrorHandler: Custom error handler for handling auth errors (optional).
  • TokenExtractor: Extracts the token from the request header (optional).

Example

import (
    "github.com/BrunoCiccarino/GopherLight/middleware"
)

config := middleware.JWTConfig{
    SecretKey: []byte("your_secret_key"),
}
app.Use(middleware.NewAuthMiddleware(config))

CORS Middleware

Need to allow cross-origin requests? No problem! Our CORSMiddleware configures the Cross-Origin Resource Sharing (CORS) settings to make your API accessible from other domains.

Config Options

  • AllowOrigin: Set to "*" to allow any origin or specify a domain (e.g., "http://example.com").
  • AllowMethods: Which HTTP methods are allowed? Common choices include "GET", "POST", etc.
  • AllowHeaders: Specify which headers clients can use.
  • AllowCredentials: Set to true if you want cookies or HTTP auth to be included.
  • ExposeHeaders: Let the client read specific headers from the response.
  • MaxAge: Cache time (in seconds) for preflight requests.

Example

corsOptions := middleware.CORSOptions{
    AllowOrigin: "*",
    AllowMethods: []string{"GET", "POST"},
}
app.Use(middleware.CORSMiddleware(corsOptions))

CSRF Middleware

Our CSRFMiddleware protects against Cross-Site Request Forgery by validating a CSRF token sent with each request. Use GenerateCSRFToken() to create a secure token, then validate it with your own isValidToken function.

Example

app.Use(middleware.CSRFMiddleware(func(token string) bool {
    return token == "your_valid_token"
}))

And don’t forget to generate tokens with:

csrfToken := middleware.GenerateCSRFToken()

Logging Middleware

Want to keep track of what’s happening on your server? LoggingMiddleware logs each request, including the method, path, and time taken. It’s a great way to stay informed on app performance and any unusual activity.

Example

app.Use(middleware.LoggingMiddleware)

Each request will be logged like this:

  • Started: Logs the request start time.
  • Completed: Logs when the request finishes, including the duration.

Timeout Middleware

Avoid those endless waits by setting time limits on request processing with TimeoutMiddleware. This middleware will cancel the request if it doesn’t complete in time, sending a 504 Gateway Timeout status to the client.

Example

import (
    "time"
    "github.com/BrunoCiccarino/GopherLight/middleware"
)

timeout := 2 * time.Second
app.Use(middleware.TimeoutMiddleware(timeout))

The Plugin Interface

The Plugin interface is super simple but super powerful. It gives you a single method: Register. This lets you hook into the app’s routing system to add any routes you need—whether it’s a new API endpoint, a webhook, or anything else you can imagine.

The Register Method
Here’s the magic part of the Plugin interface:

type Plugin interface {
    Register(route func(method, path string, handler func(req *req.Request, res *req.Response)))
}

The Register method accepts a route function that lets you define new routes in your plugin by specifying:

  • method: HTTP method (e.g., "GET", "POST", etc.)
  • path: The route path (e.g., "/my-plugin-route")
  • handler: The function to execute when the route is hit. This function receives:
    • req: The request object with access to query parameters, headers, and body.
    • res: The response object to send data back to the client.

Example Plugin

Let’s say you want to create a plugin that adds a simple endpoint at /hello-plugin to greet users. Here’s what the plugin would look like:

package main

import (
    "github.com/BrunoCiccarino/GopherLight/plugins"
    "github.com/BrunoCiccarino/GopherLight/req"
)

type HelloPlugin struct{}

// Register adds a new route for the HelloPlugin.
func (p *HelloPlugin) Register(route func(method, path string, handler func(req *req.Request, res *req.Response))) {
    route("GET", "/hello-plugin", func(req *req.Request, res *req.Response) {
        res.Send("Hello from the HelloPlugin!")
    })
}

Adding the Plugin to Your App

To load a plugin, simply create an instance and call Register in your main app setup:

package main

import (
    "github.com/BrunoCiccarino/GopherLight/router"
)

func main() {
    app := router.NewApp()
    helloPlugin := &HelloPlugin{}
    helloPlugin.Register(app.Route)

    app.Listen(":3333")
}

Customizing Your Plugins

Each plugin can add as many routes as needed. Just call route multiple times in your Register function to define additional endpoints. Use different HTTP methods, paths, and handlers to shape your plugin’s functionality however you want.

Release Statement This article is reproduced at: https://dev.to/gopherlight/how-to-write-apis-like-a-pro-in-go-with-gopherlight-3b97?1 If there is any infringement, please contact [email protected] delete
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3