Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
d8d771aec6 | |||
1e66a221e0 | |||
df318682fa | |||
af1e58bce9 | |||
940e86bd8d | |||
5263cba44a |
2
.github/workflows/nfctl.yml
vendored
2
.github/workflows/nfctl.yml
vendored
@ -5,7 +5,7 @@ on:
|
|||||||
- 'release/nfctl/*'
|
- 'release/nfctl/*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RELEASE_VERSION: v24.07.14-r3
|
RELEASE_VERSION: v24.09.23-r1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-job:
|
build-job:
|
||||||
|
35
app.go
35
app.go
@ -5,13 +5,15 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/loveuer/nf/internal/bytesconv"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/loveuer/nf/internal/bytesconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -29,6 +31,8 @@ type App struct {
|
|||||||
|
|
||||||
trees methodTrees
|
trees methodTrees
|
||||||
|
|
||||||
|
pool *sync.Pool
|
||||||
|
|
||||||
maxParams uint16
|
maxParams uint16
|
||||||
maxSections uint16
|
maxSections uint16
|
||||||
|
|
||||||
@ -40,13 +44,34 @@ type App struct {
|
|||||||
removeExtraSlash bool // false
|
removeExtraSlash bool // false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) allocateContext() *Ctx {
|
||||||
|
var (
|
||||||
|
skippedNodes = make([]skippedNode, 0, a.maxSections)
|
||||||
|
v = make(Params, 0, a.maxParams)
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx := Ctx{
|
||||||
|
lock: sync.Mutex{},
|
||||||
|
app: a,
|
||||||
|
index: -1,
|
||||||
|
locals: make(map[string]any),
|
||||||
|
handlers: make([]HandlerFunc, 0),
|
||||||
|
skippedNodes: &skippedNodes,
|
||||||
|
params: &v,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ctx
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
func (a *App) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
c = newContext(a, writer, request)
|
c = a.pool.Get().(*Ctx)
|
||||||
nfe = new(Err)
|
nfe = new(Err)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
c.reset(writer, request)
|
||||||
|
|
||||||
if err = c.verify(); err != nil {
|
if err = c.verify(); err != nil {
|
||||||
if errors.As(err, nfe) {
|
if errors.As(err, nfe) {
|
||||||
_ = c.Status(nfe.Status).SendString(nfe.Msg)
|
_ = c.Status(nfe.Status).SendString(nfe.Msg)
|
||||||
@ -58,6 +83,8 @@ func (a *App) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.handleHTTPRequest(c)
|
a.handleHTTPRequest(c)
|
||||||
|
|
||||||
|
a.pool.Put(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) run(ln net.Listener) error {
|
func (a *App) run(ln net.Listener) error {
|
||||||
@ -137,9 +164,7 @@ func (a *App) addRoute(method, path string, handlers ...HandlerFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) handleHTTPRequest(c *Ctx) {
|
func (a *App) handleHTTPRequest(c *Ctx) {
|
||||||
var (
|
var err error
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
httpMethod := c.Request.Method
|
httpMethod := c.Request.Method
|
||||||
rPath := c.Request.URL.Path
|
rPath := c.Request.URL.Path
|
||||||
|
86
ctx.go
86
ctx.go
@ -6,19 +6,19 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
"html/template"
|
||||||
"github.com/loveuer/nf/internal/sse"
|
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/loveuer/nf/internal/sse"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var forwardHeaders = []string{"CF-Connecting-IP", "X-Forwarded-For", "X-Real-Ip"}
|
||||||
forwardHeaders = []string{"CF-Connecting-IP", "X-Forwarded-For", "X-Real-Ip"}
|
|
||||||
)
|
|
||||||
|
|
||||||
type Ctx struct {
|
type Ctx struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
@ -38,45 +38,29 @@ type Ctx struct {
|
|||||||
fullPath string
|
fullPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext(app *App, writer http.ResponseWriter, request *http.Request) *Ctx {
|
func (c *Ctx) reset(w http.ResponseWriter, r *http.Request) {
|
||||||
|
traceId := r.Header.Get(TraceKey)
|
||||||
var (
|
if traceId == "" {
|
||||||
traceId string
|
|
||||||
skippedNodes = make([]skippedNode, 0, app.maxSections)
|
|
||||||
v = make(Params, 0, app.maxParams)
|
|
||||||
)
|
|
||||||
|
|
||||||
if traceId = request.Header.Get(TraceKey); traceId == "" {
|
|
||||||
traceId = uuid.Must(uuid.NewV7()).String()
|
traceId = uuid.Must(uuid.NewV7()).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
c := context.WithValue(request.Context(), TraceKey, traceId)
|
c.writermem.reset(w)
|
||||||
|
|
||||||
ctx := &Ctx{
|
c.Request = r.WithContext(context.WithValue(r.Context(), TraceKey, traceId))
|
||||||
lock: sync.Mutex{},
|
c.Writer = &c.writermem
|
||||||
Request: request.WithContext(c),
|
c.handlers = nil
|
||||||
path: request.URL.Path,
|
c.index = -1
|
||||||
method: request.Method,
|
c.path = r.URL.Path
|
||||||
StatusCode: 200,
|
c.method = r.Method
|
||||||
|
c.StatusCode = 200
|
||||||
|
|
||||||
app: app,
|
c.fullPath = ""
|
||||||
index: -1,
|
*c.params = (*c.params)[:0]
|
||||||
locals: map[string]interface{}{},
|
*c.skippedNodes = (*c.skippedNodes)[:0]
|
||||||
handlers: make([]HandlerFunc, 0),
|
for key := range c.locals {
|
||||||
skippedNodes: &skippedNodes,
|
delete(c.locals, key)
|
||||||
params: &v,
|
|
||||||
}
|
}
|
||||||
|
c.writermem.Header().Set(TraceKey, traceId)
|
||||||
ctx.writermem = responseWriter{
|
|
||||||
ResponseWriter: writer,
|
|
||||||
size: -1,
|
|
||||||
status: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Writer = &ctx.writermem
|
|
||||||
ctx.writermem.Header().Set(TraceKey, traceId)
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ctx) Locals(key string, value ...interface{}) interface{} {
|
func (c *Ctx) Locals(key string, value ...interface{}) interface{} {
|
||||||
@ -108,9 +92,7 @@ func (c *Ctx) Path(overWrite ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ctx) Cookies(key string, defaultValue ...string) string {
|
func (c *Ctx) Cookies(key string, defaultValue ...string) string {
|
||||||
var (
|
dv := ""
|
||||||
dv = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(defaultValue) > 0 {
|
if len(defaultValue) > 0 {
|
||||||
dv = defaultValue[0]
|
dv = defaultValue[0]
|
||||||
@ -295,10 +277,17 @@ func (c *Ctx) Status(code int) *Ctx {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set set response header
|
||||||
func (c *Ctx) Set(key string, value string) {
|
func (c *Ctx) Set(key string, value string) {
|
||||||
c.Writer.Header().Set(key, value)
|
c.Writer.Header().Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddHeader add response header
|
||||||
|
func (c *Ctx) AddHeader(key string, value string) {
|
||||||
|
c.Writer.Header().Add(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeader set response header
|
||||||
func (c *Ctx) SetHeader(key string, value string) {
|
func (c *Ctx) SetHeader(key string, value string) {
|
||||||
c.Writer.Header().Set(key, value)
|
c.Writer.Header().Set(key, value)
|
||||||
}
|
}
|
||||||
@ -355,6 +344,21 @@ func (c *Ctx) HTML(html string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Ctx) RenderHTML(name, html string, obj any) error {
|
||||||
|
c.SetHeader("Content-Type", "text/html")
|
||||||
|
t, err := template.New(name).Parse(html)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.Execute(c.Writer, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Ctx) Redirect(url string, code int) error {
|
||||||
|
http.Redirect(c.Writer, c.Request, url, code)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Ctx) Write(data []byte) (int, error) {
|
func (c *Ctx) Write(data []byte) (int, error) {
|
||||||
return c.Writer.Write(data)
|
return c.Writer.Write(data)
|
||||||
}
|
}
|
||||||
|
12
nf.go
12
nf.go
@ -1,5 +1,7 @@
|
|||||||
package nf
|
package nf
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
banner = " _ _ _ ___ _ \n | \\| |___| |_ | __|__ _ _ _ _ __| |\n | .` / _ \\ _| | _/ _ \\ || | ' \\/ _` |\n |_|\\_\\___/\\__| |_|\\___/\\_,_|_||_\\__,_|\n "
|
banner = " _ _ _ ___ _ \n | \\| |___| |_ | __|__ _ _ _ _ __| |\n | .` / _ \\ _| | _/ _ \\ || | ' \\/ _` |\n |_|\\_\\___/\\__| |_|\\___/\\_,_|_||_\\__,_|\n "
|
||||||
_404 = "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1\"><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"><title>Not Found</title><style>body{background:#333;margin:0;color:#ccc;display:flex;align-items:center;max-height:100vh;height:100vh;justify-content:center}textarea{min-height:5rem;min-width:20rem;text-align:center;border:none;background:0 0;color:#ccc;resize:none;user-input:none;user-select:none;cursor:default;-webkit-user-select:none;-webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;outline:0}</style></head><body><textarea id=\"banner\" readonly=\"readonly\"></textarea><script type=\"text/javascript\">let htmlCodes = [\n ' _ _ _ ___ _ ',\n '| \\\\| |___| |_ | __|__ _ _ _ _ __| |',\n '| .` / _ \\\\ _| | _/ _ \\\\ || | \\' \\\\/ _` |',\n '|_|\\\\_\\\\___/\\\\__| |_|\\\\___/\\\\_,_|_||_\\\\__,_|'\n].join('\\n');\ndocument.querySelector('#banner').value = htmlCodes</script></body></html>"
|
_404 = "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1\"><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"><title>Not Found</title><style>body{background:#333;margin:0;color:#ccc;display:flex;align-items:center;max-height:100vh;height:100vh;justify-content:center}textarea{min-height:5rem;min-width:20rem;text-align:center;border:none;background:0 0;color:#ccc;resize:none;user-input:none;user-select:none;cursor:default;-webkit-user-select:none;-webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;outline:0}</style></head><body><textarea id=\"banner\" readonly=\"readonly\"></textarea><script type=\"text/javascript\">let htmlCodes = [\n ' _ _ _ ___ _ ',\n '| \\\\| |___| |_ | __|__ _ _ _ _ __| |',\n '| .` / _ \\\\ _| | _/ _ \\\\ || | \\' \\\\/ _` |',\n '|_|\\\\_\\\\___/\\\\__| |_|\\\\___/\\\\_,_|_||_\\\\__,_|'\n].join('\\n');\ndocument.querySelector('#banner').value = htmlCodes</script></body></html>"
|
||||||
@ -28,8 +30,7 @@ type Config struct {
|
|||||||
MethodNotAllowedHandler HandlerFunc `json:"-"`
|
MethodNotAllowedHandler HandlerFunc `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var defaultConfig = &Config{
|
||||||
defaultConfig = &Config{
|
|
||||||
BodyLimit: 4 * 1024 * 1024,
|
BodyLimit: 4 * 1024 * 1024,
|
||||||
NotFoundHandler: func(c *Ctx) error {
|
NotFoundHandler: func(c *Ctx) error {
|
||||||
c.Set("Content-Type", MIMETextHTML)
|
c.Set("Content-Type", MIMETextHTML)
|
||||||
@ -42,7 +43,6 @@ var (
|
|||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
func New(config ...Config) *App {
|
func New(config ...Config) *App {
|
||||||
app := &App{
|
app := &App{
|
||||||
@ -52,6 +52,8 @@ func New(config ...Config) *App {
|
|||||||
root: true,
|
root: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pool: &sync.Pool{},
|
||||||
|
|
||||||
redirectTrailingSlash: true, // true
|
redirectTrailingSlash: true, // true
|
||||||
redirectFixedPath: false, // false
|
redirectFixedPath: false, // false
|
||||||
handleMethodNotAllowed: true, // false
|
handleMethodNotAllowed: true, // false
|
||||||
@ -89,5 +91,9 @@ func New(config ...Config) *App {
|
|||||||
app.Use(NewRecover(true))
|
app.Use(NewRecover(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.pool.New = func() any {
|
||||||
|
return app.allocateContext()
|
||||||
|
}
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ var (
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLogger = &logger{
|
DefaultLogger = &logger{
|
||||||
Mutex: sync.Mutex{},
|
Mutex: sync.Mutex{},
|
||||||
timeFormat: "2006-01-02T15:04:05",
|
timeFormat: "2006-01-02T15:04:05",
|
||||||
writer: os.Stdout,
|
writer: os.Stdout,
|
||||||
@ -36,32 +36,32 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func SetTimeFormat(format string) {
|
func SetTimeFormat(format string) {
|
||||||
defaultLogger.SetTimeFormat(format)
|
DefaultLogger.SetTimeFormat(format)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetLogLevel(level LogLevel) {
|
func SetLogLevel(level LogLevel) {
|
||||||
defaultLogger.SetLogLevel(level)
|
DefaultLogger.SetLogLevel(level)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debug(msg string, data ...any) {
|
func Debug(msg string, data ...any) {
|
||||||
defaultLogger.Debug(msg, data...)
|
DefaultLogger.Debug(msg, data...)
|
||||||
}
|
}
|
||||||
func Info(msg string, data ...any) {
|
func Info(msg string, data ...any) {
|
||||||
defaultLogger.Info(msg, data...)
|
DefaultLogger.Info(msg, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warn(msg string, data ...any) {
|
func Warn(msg string, data ...any) {
|
||||||
defaultLogger.Warn(msg, data...)
|
DefaultLogger.Warn(msg, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Error(msg string, data ...any) {
|
func Error(msg string, data ...any) {
|
||||||
defaultLogger.Error(msg, data...)
|
DefaultLogger.Error(msg, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Panic(msg string, data ...any) {
|
func Panic(msg string, data ...any) {
|
||||||
defaultLogger.Panic(msg, data...)
|
DefaultLogger.Panic(msg, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fatal(msg string, data ...any) {
|
func Fatal(msg string, data ...any) {
|
||||||
defaultLogger.Fatal(msg, data...)
|
DefaultLogger.Fatal(msg, data...)
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,16 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
"github.com/loveuer/nf/nft/log"
|
"github.com/loveuer/nf/nft/log"
|
||||||
"github.com/loveuer/nf/nft/nfctl/clone"
|
"github.com/loveuer/nf/nft/nfctl/clone"
|
||||||
"github.com/loveuer/nf/nft/nfctl/opt"
|
"github.com/loveuer/nf/nft/nfctl/opt"
|
||||||
"github.com/loveuer/nf/nft/nfctl/tp"
|
"github.com/loveuer/nf/nft/nfctl/tp"
|
||||||
"github.com/loveuer/nf/nft/nfctl/version"
|
"github.com/loveuer/nf/nft/nfctl/version"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -29,12 +30,12 @@ nfctl new {project} --template http://username:token@my.gitlab.com/my-zone/my-re
|
|||||||
disableInit bool
|
disableInit bool
|
||||||
|
|
||||||
preTemplateMap = map[string]string{
|
preTemplateMap = map[string]string{
|
||||||
"ultone": "https://gitcode.com/loveuer/ultone.git",
|
"ultone": "https://gitea.loveuer.com/loveuer/ultone.git",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func initNew() {
|
func initNew() {
|
||||||
cmdNew.Flags().StringVarP(&template, "template", "t", "", "template name/url[example:ultone, https://github.com/xxx/yyy.git]")
|
cmdNew.Flags().StringVarP(&template, "template", "t", "ultone", "template name/url[example:ultone, https://github.com/xxx/yyy.git]")
|
||||||
cmdNew.Flags().BoolVar(&disableInit, "without-init", false, "don't run template init script")
|
cmdNew.Flags().BoolVar(&disableInit, "without-init", false, "don't run template init script")
|
||||||
|
|
||||||
cmdNew.RunE = func(cmd *cobra.Command, args []string) error {
|
cmdNew.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
@ -44,6 +45,7 @@ func initNew() {
|
|||||||
err error
|
err error
|
||||||
urlIns *url.URL
|
urlIns *url.URL
|
||||||
pwd string
|
pwd string
|
||||||
|
moduleName string
|
||||||
projectDir string
|
projectDir string
|
||||||
initBs []byte
|
initBs []byte
|
||||||
renderBs []byte
|
renderBs []byte
|
||||||
@ -58,13 +60,14 @@ func initNew() {
|
|||||||
return fmt.Errorf("get work dir err")
|
return fmt.Errorf("get work dir err")
|
||||||
}
|
}
|
||||||
|
|
||||||
projectDir = path.Join(pwd, args[0])
|
moduleName = args[0]
|
||||||
|
projectDir = path.Join(pwd, path.Base(args[0]))
|
||||||
|
|
||||||
if _, err = os.Stat(projectDir); !errors.Is(err, os.ErrNotExist) {
|
if _, err = os.Stat(projectDir); !errors.Is(err, os.ErrNotExist) {
|
||||||
return fmt.Errorf("project folder already exist")
|
return fmt.Errorf("project folder already exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = os.MkdirAll(projectDir, 0750); err != nil {
|
if err = os.MkdirAll(projectDir, 0o750); err != nil {
|
||||||
return fmt.Errorf("create project dir err: %v", err)
|
return fmt.Errorf("create project dir err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +104,8 @@ func initNew() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if renderBs, err = tp.RenderVar(initBs, map[string]any{
|
if renderBs, err = tp.RenderVar(initBs, map[string]any{
|
||||||
"PROJECT_NAME": args[0],
|
"PROJECT_NAME": projectDir,
|
||||||
|
"MODULE_NAME": moduleName,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("render template init script err: %v", err)
|
return fmt.Errorf("render template init script err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,15 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/loveuer/nf/nft/nfctl/cmd"
|
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/loveuer/nf/nft/nfctl/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
//if !(len(os.Args) >= 2 && os.Args[1] == "version") {
|
|
||||||
// version.Check(5)
|
|
||||||
//}
|
|
||||||
|
|
||||||
_ = cmd.Root.ExecuteContext(ctx)
|
_ = cmd.Root.ExecuteContext(ctx)
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ package resp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/loveuer/nf"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/loveuer/nf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleEmptyMsg(status uint32, msg string) string {
|
func handleEmptyMsg(status uint32, msg string) string {
|
||||||
@ -102,6 +103,18 @@ func Resp403(c *nf.Ctx, data any, msgs ...string) error {
|
|||||||
return Resp(c, 403, msg, err, data)
|
return Resp(c, 403, msg, err, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Resp418(c *nf.Ctx, data any, msgs ...string) error {
|
||||||
|
msg := MSG418
|
||||||
|
err := ""
|
||||||
|
|
||||||
|
if len(msgs) > 0 && msgs[0] != "" {
|
||||||
|
msg = fmt.Sprintf("%s: %s", msg, strings.Join(msgs, "; "))
|
||||||
|
err = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resp(c, 418, msg, err, data)
|
||||||
|
}
|
||||||
|
|
||||||
func Resp429(c *nf.Ctx, data any, msgs ...string) error {
|
func Resp429(c *nf.Ctx, data any, msgs ...string) error {
|
||||||
msg := MSG429
|
msg := MSG429
|
||||||
err := ""
|
err := ""
|
||||||
|
@ -7,6 +7,7 @@ const (
|
|||||||
MSG401 = "登录已过期, 请重新登录"
|
MSG401 = "登录已过期, 请重新登录"
|
||||||
MSG403 = "请求权限不足"
|
MSG403 = "请求权限不足"
|
||||||
MSG404 = "请求资源未找到"
|
MSG404 = "请求资源未找到"
|
||||||
|
MSG418 = "请求条件不满足, 请稍后再试"
|
||||||
MSG429 = "请求过于频繁, 请稍后再试"
|
MSG429 = "请求过于频繁, 请稍后再试"
|
||||||
MSG500 = "服务器开小差了, 请稍后再试"
|
MSG500 = "服务器开小差了, 请稍后再试"
|
||||||
MSG501 = "功能开发中, 尽情期待"
|
MSG501 = "功能开发中, 尽情期待"
|
||||||
|
35
readme.md
35
readme.md
@ -5,6 +5,7 @@
|
|||||||
##### basic usage
|
##### basic usage
|
||||||
|
|
||||||
- get param
|
- get param
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func main() {
|
func main() {
|
||||||
app := nf.New()
|
app := nf.New()
|
||||||
@ -19,6 +20,7 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
- parse request query
|
- parse request query
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func handleQuery(c *nf.Ctx) error {
|
func handleQuery(c *nf.Ctx) error {
|
||||||
type Req struct {
|
type Req struct {
|
||||||
@ -40,6 +42,7 @@ func handleQuery(c *nf.Ctx) error {
|
|||||||
```
|
```
|
||||||
|
|
||||||
- parse application/json body
|
- parse application/json body
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func handlePost(c *nf.Ctx) error {
|
func handlePost(c *nf.Ctx) error {
|
||||||
type Req struct {
|
type Req struct {
|
||||||
@ -65,3 +68,35 @@ func handlePost(c *nf.Ctx) error {
|
|||||||
return c.JSON(nf.Map{"struct": req, "map": reqMap})
|
return c.JSON(nf.Map{"struct": req, "map": reqMap})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- pass local value
|
||||||
|
|
||||||
|
```go
|
||||||
|
type User struct {
|
||||||
|
Id int
|
||||||
|
Username string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := nf.New()
|
||||||
|
app.Use(auth())
|
||||||
|
|
||||||
|
app.Get("/item/list", list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func auth() nf.HandlerFunc {
|
||||||
|
return func(c *nf.Ctx) error {
|
||||||
|
c.Locals("user", &User{Id: 1, Username:"user"})
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func list(c *nf.Ctx) error {
|
||||||
|
user, ok := c.Locals("user").(*User)
|
||||||
|
if !ok {
|
||||||
|
return c.Status(401).SendString("login required")
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Reference in New Issue
Block a user