mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
Happy New Year To Everyone! 🎅
Today is my Birthday too ^_^
This commit is contained in:
parent
50faf05528
commit
56754ff5cc
|
@ -23,10 +23,11 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
|
||||||
|
|
||||||
Changes apply to `main` branch.
|
Changes apply to `main` branch.
|
||||||
|
|
||||||
|
- Add `x/errors.ReadPayload`, `ReadQuery`, `ReadPaginationOptions`, `Handle`, `HandleCreate`, `HandleCreateResponse`, `HandleUpdate` and `HandleDelete` package-level functions as helpers for common actions.
|
||||||
- Add `x/jsonx.GetSimpleDateRange(date, jsonx.WeekRange, time.Monday, time.Sunday)` which returns all dates between the given range and start/end weekday values for WeekRange.
|
- Add `x/jsonx.GetSimpleDateRange(date, jsonx.WeekRange, time.Monday, time.Sunday)` which returns all dates between the given range and start/end weekday values for WeekRange.
|
||||||
- Add `x/timex.GetMonthDays` and `x/timex.GetMonthEnd` functions.
|
- Add `x/timex.GetMonthDays` and `x/timex.GetMonthEnd` functions.
|
||||||
- Add `iris.CookieDomain` and `iris.CookieOverride` cookie options to handle [#2309](https://github.com/kataras/iris/issues/2309).
|
- Add `iris.CookieDomain` and `iris.CookieOverride` cookie options to handle [#2309](https://github.com/kataras/iris/issues/2309).
|
||||||
- New `x/errors.ErrorCodeName.MapErrorFunc`, `x/errors.ErrorCodeName.MapErrors`, `x/errors.ErrorCodeName.Wrap` methods and `x/errors.HandleError` package-level function.
|
- New `x/errors.ErrorCodeName.MapErrorFunc`, `MapErrors`, `Wrap` methods and `x/errors.HandleError` package-level function.
|
||||||
|
|
||||||
# Sun, 05 Nov 2023 | v12.2.8
|
# Sun, 05 Nov 2023 | v12.2.8
|
||||||
|
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2016-2023, Gerasimos (Makis) Maropoulos
|
Copyright (c) 2016-2024, Gerasimos (Makis) Maropoulos
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
28
README.md
28
README.md
|
@ -4,6 +4,34 @@
|
||||||
|
|
||||||
Try the official [Iris Command Line Interface](https://github.com/kataras/iris-cli) today! -->
|
Try the official [Iris Command Line Interface](https://github.com/kataras/iris-cli) today! -->
|
||||||
|
|
||||||
|
# 🎅 Happy new year to everyone!
|
||||||
|
|
||||||
|
```
|
||||||
|
A new year is here, full of hope and cheer
|
||||||
|
A time to celebrate, and appreciate
|
||||||
|
the past year's achievements, and the future's improvements.
|
||||||
|
|
||||||
|
We are proud to present, our open-source project
|
||||||
|
Iris web framework, a fast and elegant way to make
|
||||||
|
Web applications, with ease and satisfaction.
|
||||||
|
|
||||||
|
Iris is built with Go, a language you should know
|
||||||
|
It offers high performance, and great concurrency.
|
||||||
|
It has a rich ecosystem, and a friendly community.
|
||||||
|
|
||||||
|
Iris is designed to be, simple and flexible
|
||||||
|
It has a modular structure, and a powerful router.
|
||||||
|
It supports middleware, and many features.
|
||||||
|
|
||||||
|
Iris is more than a tool, it is a vision
|
||||||
|
To empower developers, and inspire creations
|
||||||
|
to make the web better, and brighter.
|
||||||
|
|
||||||
|
We thank you for your support, and your feedback.
|
||||||
|
We hope you enjoy using Iris, and find it useful.
|
||||||
|
We wish you a happy new year, and a successful career.
|
||||||
|
```
|
||||||
|
|
||||||
# <a href="https://iris-go.com"><img src="https://iris-go.com/images/logo-new-lq-45.png"></a> Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a> </a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH_HANT.md"><img width="20px" src="https://iris-go.com/images/flag-taiwan.svg" /></a> <a href="README_ZH_HANS.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a> <a href="README_VN.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-vietnam.svg" /></a>
|
# <a href="https://iris-go.com"><img src="https://iris-go.com/images/logo-new-lq-45.png"></a> Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a> </a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH_HANT.md"><img width="20px" src="https://iris-go.com/images/flag-taiwan.svg" /></a> <a href="README_ZH_HANS.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a> <a href="README_VN.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-vietnam.svg" /></a>
|
||||||
|
|
||||||
[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
|
[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
|
||||||
|
|
|
@ -59,7 +59,7 @@ var errorCodeMap = make(map[ErrorCodeName]ErrorCode)
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// var (
|
// var (
|
||||||
// NotFound = errors.E("NOT_FOUND", http.StatusNotFound)
|
// NotFound = errors.E("NOT_FOUND", http.StatusNotFound)
|
||||||
// )
|
// )
|
||||||
// ...
|
// ...
|
||||||
// NotFound.Details(ctx, "resource not found", "user with id: %q was not found", userID)
|
// NotFound.Details(ctx, "resource not found", "user with id: %q was not found", userID)
|
||||||
|
@ -118,6 +118,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// errorFuncCodeMap is a read-only map of error code names and their error functions.
|
// errorFuncCodeMap is a read-only map of error code names and their error functions.
|
||||||
|
// See HandleError package-level function.
|
||||||
var errorFuncCodeMap = make(map[ErrorCodeName][]func(error) error)
|
var errorFuncCodeMap = make(map[ErrorCodeName][]func(error) error)
|
||||||
|
|
||||||
// HandleError handles an error by sending it to the client
|
// HandleError handles an error by sending it to the client
|
||||||
|
|
145
x/errors/handlers.go
Normal file
145
x/errors/handlers.go
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12/context"
|
||||||
|
"github.com/kataras/iris/v12/x/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadPayload reads a JSON payload from the context and returns it as a generic type T.
|
||||||
|
// It also returns a boolean value indicating whether the read was successful or not.
|
||||||
|
// If the read fails, it sends an appropriate error response to the client.
|
||||||
|
func ReadPayload[T any](ctx *context.Context) (T, bool) {
|
||||||
|
var payload T
|
||||||
|
err := ctx.ReadJSON(&payload)
|
||||||
|
if err != nil {
|
||||||
|
if vErrs, ok := AsValidationErrors(err); ok {
|
||||||
|
InvalidArgument.Data(ctx, "validation failure", vErrs)
|
||||||
|
} else {
|
||||||
|
InvalidArgument.Details(ctx, "unable to parse body", err.Error())
|
||||||
|
}
|
||||||
|
return payload, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadQuery reads URL query values from the context and returns it as a generic type T.
|
||||||
|
// It also returns a boolean value indicating whether the read was successful or not.
|
||||||
|
// If the read fails, it sends an appropriate error response to the client.
|
||||||
|
func ReadQuery[T any](ctx *context.Context) (T, bool) {
|
||||||
|
var payload T
|
||||||
|
err := ctx.ReadQuery(&payload)
|
||||||
|
if err != nil {
|
||||||
|
if vErrs, ok := AsValidationErrors(err); ok {
|
||||||
|
InvalidArgument.Data(ctx, "validation failure", vErrs)
|
||||||
|
} else {
|
||||||
|
InvalidArgument.Details(ctx, "unable to parse query", err.Error())
|
||||||
|
}
|
||||||
|
return payload, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadPaginationOptions reads the ListOptions from the URL Query and
|
||||||
|
// any filter options of generic T from the request body.
|
||||||
|
func ReadPaginationOptions[T /* T is FilterOptions */ any](ctx *context.Context) (pagination.ListOptions, T, bool) {
|
||||||
|
list, ok := ReadQuery[pagination.ListOptions](ctx)
|
||||||
|
if !ok {
|
||||||
|
var t T
|
||||||
|
return list, t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
filter, ok := ReadPayload[T](ctx)
|
||||||
|
if !ok {
|
||||||
|
var t T
|
||||||
|
return list, t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, filter, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle handles a generic response and error from a service call and sends a JSON response to the context.
|
||||||
|
// It returns a boolean value indicating whether the handle was successful or not.
|
||||||
|
// If the error is not nil, it calls HandleError to send an appropriate error response to the client.
|
||||||
|
func Handle(ctx *context.Context, resp interface{}, err error) bool {
|
||||||
|
if HandleError(ctx, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.JSON(resp) == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDPayload is a simple struct which describes a json id value.
|
||||||
|
type IDPayload struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleCreate handles a create operation and sends a JSON response with the created id to the client.
|
||||||
|
// It returns a boolean value indicating whether the handle was successful or not.
|
||||||
|
// If the error is not nil, it calls HandleError to send an appropriate error response to the client.
|
||||||
|
// If the id is not empty, it sets the status code to 201 (Created) and sends the id as a JSON payload.
|
||||||
|
func HandleCreate(ctx *context.Context, id string, err error) bool {
|
||||||
|
if HandleError(ctx, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.StatusCode(http.StatusCreated)
|
||||||
|
|
||||||
|
if id != "" {
|
||||||
|
ctx.JSON(IDPayload{ID: id})
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleCreateResponse handles a create operation and sends a JSON response with the created resource to the client.
|
||||||
|
// It returns a boolean value indicating whether the handle was successful or not.
|
||||||
|
// If the error is not nil, it calls HandleError to send an appropriate error response to the client.
|
||||||
|
// If the response is not nil, it sets the status code to 201 (Created) and sends the response as a JSON payload.
|
||||||
|
func HandleCreateResponse(ctx *context.Context, resp interface{}, err error) bool {
|
||||||
|
if HandleError(ctx, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.StatusCode(http.StatusCreated)
|
||||||
|
if resp != nil {
|
||||||
|
return ctx.JSON(resp) == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleUpdate handles an update operation and sends a status code to the client.
|
||||||
|
// It returns a boolean value indicating whether the handle was successful or not.
|
||||||
|
// If the error is not nil, it calls HandleError to send an appropriate error response to the client.
|
||||||
|
// If the updated value is true, it sets the status code to 204 (No Content).
|
||||||
|
// If the updated value is false, it sets the status code to 304 (Not Modified).
|
||||||
|
func HandleUpdate(ctx *context.Context, updated bool, err error) bool {
|
||||||
|
if HandleError(ctx, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
ctx.StatusCode(http.StatusNoContent)
|
||||||
|
} else {
|
||||||
|
ctx.StatusCode(http.StatusNotModified)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDelete handles a delete operation and sends a status code to the client.
|
||||||
|
// If the error is not nil, it calls HandleError to send an appropriate error response to the client.
|
||||||
|
// It sets the status code to 204 (No Content).
|
||||||
|
func HandleDelete(ctx *context.Context, err error) bool {
|
||||||
|
if HandleError(ctx, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.StatusCode(http.StatusNoContent)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user