118 lines
2.5 KiB
Go
118 lines
2.5 KiB
Go
/*
|
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
|
*
|
|
* This work is published and licensed under a Creative Commons
|
|
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
|
*
|
|
* Distribution of this work is permitted, but commercial use and
|
|
* modifications are strictly prohibited.
|
|
*/
|
|
package router
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type Context struct {
|
|
Ctx context.Context
|
|
Request *http.Request
|
|
Writer http.ResponseWriter
|
|
PathMap map[string]string
|
|
StatusCode int
|
|
}
|
|
|
|
func NewContext(writer http.ResponseWriter, request *http.Request) *Context {
|
|
ctx := context.Background()
|
|
rctx := &Context{
|
|
Writer: writer,
|
|
Request: request,
|
|
Ctx: ctx,
|
|
PathMap: make(map[string]string),
|
|
}
|
|
return rctx
|
|
}
|
|
|
|
// Request
|
|
func (rctx *Context) GetSubpath(key string) (string, bool) {
|
|
value, exists := rctx.PathMap[key]
|
|
return value, exists
|
|
}
|
|
|
|
func (rctx *Context) GetQuery(key string) string {
|
|
return rctx.Request.URL.Query().Get(key)
|
|
}
|
|
|
|
func (rctx *Context) GetHeader(key string) string {
|
|
return rctx.Request.Header.Get(key)
|
|
}
|
|
|
|
func (rctx *Context) GetHeaders() http.Header {
|
|
return rctx.Request.Header
|
|
}
|
|
|
|
func (rctx *Context) GetContext() context.Context {
|
|
return rctx.Request.Context()
|
|
}
|
|
|
|
// Binding
|
|
|
|
const emptyJSON = "{}"
|
|
|
|
func (ctx *Context) BindJSON(obj any) error {
|
|
buffer := bytes.NewBuffer(nil)
|
|
_, err := io.Copy(buffer, ctx.Request.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
reqBody := buffer.Bytes()
|
|
if len(reqBody) == 0 {
|
|
reqBody = []byte(emptyJSON)
|
|
}
|
|
err = json.Unmarshal(reqBody, obj)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (ctx *Context) BindQuery(obj any) error {
|
|
qMap := make(map[string]string)
|
|
for key, val := range ctx.Request.URL.Query() {
|
|
if len(val) == 1 {
|
|
qMap[key] = val[0]
|
|
}
|
|
}
|
|
return bindObj(obj, qMap, "param")
|
|
}
|
|
|
|
// Response
|
|
func (rctx *Context) SetHeader(key, value string) {
|
|
rctx.Writer.Header().Set(key, value)
|
|
}
|
|
|
|
func (rctx *Context) SetStatus(httpStatus int) {
|
|
rctx.StatusCode = httpStatus
|
|
rctx.Writer.WriteHeader(httpStatus)
|
|
}
|
|
|
|
func (rctx *Context) SendJSON(statusCode int, payload any) {
|
|
rctx.Writer.Header().Set("Content-Type", "application/json")
|
|
rctx.Writer.WriteHeader(statusCode)
|
|
json.NewEncoder(rctx.Writer).Encode(payload)
|
|
}
|
|
|
|
func (rctx *Context) SendText(statusCode int, payload string) {
|
|
rctx.Writer.Header().Set("Content-Type", "text/plain")
|
|
rctx.Writer.WriteHeader(statusCode)
|
|
rctx.Writer.Write([]byte(payload))
|
|
}
|
|
|
|
func (rctx *Context) SendBytes(statusCode int, payload []byte) {
|
|
rctx.Writer.WriteHeader(statusCode)
|
|
rctx.Writer.Write(payload)
|
|
}
|