This guide will help you get started with host-http, from installation to building your first web API.
- Go 1.24 or later
- Basic understanding of Go and HTTP concepts
Create a new Go module and install host-http:
mkdir my-api-project
cd my-api-project
go mod init my-api-project
go get github.com/Bofry/host-httpCreate main.go:
package main
import (
http "github.com/Bofry/host-http"
"github.com/Bofry/host-http/response"
)
// Define your API structure
//go:generate gen-host-http-request
type RequestManager struct {
*UserRequest `url:"/users"`
*HealthRequest `url:"/health"`
}
// User API handler
type UserRequest struct{}
func (r *UserRequest) Get(w http.ResponseWriter, req *http.Request) {
users := []map[string]interface{}{
{"id": 1, "name": "John Doe", "email": "john@example.com"},
{"id": 2, "name": "Jane Smith", "email": "jane@example.com"},
}
response.JSON.Success(w, users)
}
func (r *UserRequest) Post(w http.ResponseWriter, req *http.Request) {
// In real applications, you would parse request body
newUser := map[string]interface{}{
"id": 3,
"name": "New User",
"email": "newuser@example.com",
}
response.JSON.Success(w, newUser)
}
// Health check handler
type HealthRequest struct{}
func (r *HealthRequest) Get(w http.ResponseWriter, req *http.Request) {
response.JSON.Success(w, map[string]string{
"status": "healthy",
"version": "1.0.0",
})
}
// Application struct
type App struct{}
func main() {
app := &App{}
http.Startup(app).
Middlewares(
http.UseRequestManager(&RequestManager{}),
http.UseErrorHandler(func(w http.ResponseWriter, req *http.Request, err any) {
response.JSON.Failure(w, err, http.StatusInternalServerError)
}),
).
Run()
}go run main.goYou should see output similar to:
2025/09/07 23:04:17 [host-http] % Notice: Server listening on address :8080
Test the endpoints:
# Get users
curl http://localhost:8080/users
# Create a user (POST)
curl -X POST http://localhost:8080/users
# Health check
curl http://localhost:8080/healthhost-http provides sensible defaults to get you started quickly.
The framework automatically configures:
- Listen Address:
:8080- Server listens on port 8080 by default - Version:
1.0.0- Default application version - Compression: Disabled by default
Override defaults using environment variables:
# Override port only
HTTP_PORT=3000 go run main.go
# Override full listen address
HTTP_LISTEN_ADDRESS=localhost:9090 go run main.goFor more control, define your own configuration structure:
package main
import http "github.com/Bofry/host-http"
type Config struct {
ListenAddress string `yaml:"ListenAddress"`
EnableCompress bool `yaml:"EnableCompress"`
ServerName string `yaml:"ServerName"`
}
type App struct {
Host *http.Host `host:""`
Config *Config `config:""`
ServiceProvider *ServiceProvider `serviceProvider:""`
}
type ServiceProvider struct{}
func main() {
app := &App{
Config: &Config{
ListenAddress: ":3000",
EnableCompress: true,
ServerName: "MyAPI",
},
}
http.Startup(app).
Middlewares(
http.UseRequestManager(&RequestManager{}),
).
Run()
}// config.yaml
ListenAddress: ":8080"
EnableCompress: true
ServerName: "MyAPI"The framework supports automatic configuration loading from YAML files when used with the Bofry configuration system.
http.Startup(app).
Middlewares(
http.UseRequestManager(&RequestManager{}),
http.UseCorsHeader("Authorization", "Content-Type"), // Custom headers
http.UseErrorHandler(errorHandler),
).
Run()type LoggingService struct{}
func (s *LoggingService) ConfigureLogger(logger interface{}) {
// Configure your logger
}
func (s *LoggingService) CreateEventLog(ev http.EventEvidence) http.EventLog {
// Return your event log implementation
return &MyEventLog{}
}
// Add to middleware chain
http.UseLogging(&LoggingService{})// Support X-Http-Method header for method override
http.UseXHttpMethodHeader()type RequestManager struct {
*UserRequest `url:"/users" @BindMethod:"GET *FETCH"` // Map FETCH method to GET
*AdminRequest `url:"/admin" @ExpandEnv:"on"` // Enable env expansion
}type RequestManager struct {
*ApiRequest `url:"${API_PREFIX}/v1/data"` // Expands ${API_PREFIX}
}func errorHandler(w http.ResponseWriter, req *http.Request, err any) {
switch e := err.(type) {
case *failure.Failure:
response.JSON.Failure(w, e, http.StatusBadRequest)
case error:
response.JSON.Failure(w, e.Error(), http.StatusInternalServerError)
default:
response.JSON.Failure(w, "Internal server error", http.StatusInternalServerError)
}
}import "github.com/Bofry/host-http/response/failure"
func (r *UserRequest) Get(w http.ResponseWriter, req *http.Request) {
userID := req.URL.Query().Get("id")
if userID == "" {
failure.ThrowFailureMessage(failure.INVALID_ARGUMENT, "User ID is required")
return
}
// Process request...
response.JSON.Success(w, user)
}func main() {
app := &App{}
starter := http.Startup(app)
// Configure host before running
host := starter.Host()
host.SetListenAddress(":9000")
host.SetServerName("MyAPI")
starter.
Middlewares(/*...*/).
Run()
}- Read the Architecture Guide to understand the design patterns
- Learn about Middleware Development for custom middleware
- Check Best Practices for production deployment
- See Migration Guide if you're coming from host-fasthttp
If you see "address already in use" error, either:
- Change the port:
host.SetListenAddress(":9000") - Stop the process using the port
Make sure you're using the correct import alias:
import http "github.com/Bofry/host-http"Ensure your request methods follow the naming convention:
Getfor GET requestsPostfor POST requestsPutfor PUT requestsDeletefor DELETE requests