To use purely net/http (for Go 1.22+), you will want a configuration file such as:
# yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.8.0/configuration-schema.json
package: api
generate:
std-http-server: true
models: true
output: gen.goAs of Go 1.22, enhancements have been made to the routing of the net/http package in the standard library, which makes it a great starting point for implementing a server with, before needing to reach for another router or a full framework.
For instance, let's take this straightforward specification:
openapi: "3.0.0"
info:
version: 1.0.0
title: Minimal ping API server
paths:
/ping:
get:
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pong'
components:
schemas:
# base types
Pong:
type: object
required:
- ping
properties:
ping:
type: string
example: pongThis then generates code such as:
// Pong defines model for Pong.
type Pong struct {
Ping string `json:"ping"`
}
// ServerInterface represents all server handlers.
type ServerInterface interface {
// (GET /ping)
GetPing(w http.ResponseWriter, r *http.Request)
}
func HandlerFromMux(si ServerInterface, m ServeMux) http.Handler {
return HandlerWithOptions(si, StdHTTPServerOptions{
BaseRouter: m,
})
}
// HandlerWithOptions creates http.Handler with additional options
func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler {
m := options.BaseRouter
// ... omitted for brevity
m.HandleFunc("GET "+options.BaseURL+"/ping", wrapper.GetPing)
return m
}To implement this HTTP server, we need to write the following code in our api/impl.go:
import (
"encoding/json"
"net/http"
)
// optional code omitted
type Server struct{}
func NewServer() Server {
return Server{}
}
// (GET /ping)
func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
resp := Pong{
Ping: "pong",
}
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(resp)
}Now we've got our implementation, we can then write the following code to wire it up and get a running server:
import (
"log"
"net/http"
"github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/stdhttp/api"
)
func main() {
// create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
server := api.NewServer()
r := http.NewServeMux()
// get an `http.Handler` that we can use
h := api.HandlerFromMux(server, r)
s := &http.Server{
Handler: h,
Addr: "0.0.0.0:8080",
}
// And we serve HTTP until the world ends.
log.Fatal(s.ListenAndServe())
}Note
This doesn't include validation of incoming requests.
Note
If you feel like you've done everything right, but are still receiving 404 page not found errors, make sure that you've got the go directive in your go.mod set to at least 1.22, which enables the enhanced net/http routing. In practice it should be at least:
go 1.24(the
github.com/oapi-codegen/runtimemodule imported by the generated code requires Go 1.24+.)