Giter Club home page Giter Club logo

quick's Introduction

Logo do Quick

GoDoc Github Release CircleCI Go Report License CircleCI Coveralls

Quick Route Go Logo do Quick

🚀 O Quick é um gerenciador de rotas flexível e extensível para a linguagem Go. Seu objetivo é ser rápido e de alto desempenho, além de ser 100% compatível com net/http. O Quick é um projeto em constante desenvolvimento e está aberto para colaboração, todos são bem-vindos para contribuir. 😍

💡 Se você é novo na programação, o Quick é uma ótima oportunidade para começar a aprender a trabalhar com Go. Com sua facilidade de uso e recursos, você pode criar rotas personalizadas e expandir seu conhecimento na linguagem.

👍 Espero que possam participar e que gostem de Godar!!! 😍

🔍 O repositório de exemplos do Framework Quick Exemplos Quick.

🗺️| Rodmap do desenvolvimento

Tarefa Progresso
Desenvolver MaxBodySize metodos Post e Put 100%
Desenvolver Padrão de Testes Unitários 90%
Desenvolver Config em New(Config{}) não obrigatório 100%
Desenvolve suporte a Grupo de Rotas - Group Get e Post 70%
Desenvolver e relacionar ao Listen o Config 30%
Criação de função print para não usar fmt de forma demasiada 100%
Criação de função própria para Concat String 100%
Criação de benchmarking entre os.Stdout e fmt.Println 100%
Desenvolver Routes Método GET 100%
Desenvolver Routes Método GET aceitando Query String 100%
Desenvolver Routes Método GET aceitando Parametros 100%
Desenvolver Routes Método GET aceitando Query String e Parametros 100%
Desenvolver Routes Método GET aceitando expressão regular 100.%
Desenvolver Routes Método POST 100%
Desenvolver Routes Método POST aceitando JSON 100%
Desenvolver para o MÉTODO POST o parse JSON 100%
Desenvolver para o MÉTODO POST funções para acessar byte ou string do Parse 100%
Desenvolver para o MÉTODO PUT 100%
Desenvolver para o MÉTODO PUT o parse JSON 100%
Desenvolver para o MÉTODO PUT o parse JSON 100%
Desenvolver para o MÉTODO PUT funções para acessar byte ou string do Parse 100%
Desenvolver para o MÉTODO DELETE 100%
Desenvolver para o MÉTODO OPTIONS 0.%
Desenvolver para o MÉTODO CONNECT Veja mais 0.%
Desenvolver método para ListenAndServe 100%
Desenvolver método para ListenAndServeTLS (http2) 0.%
Desenvolver método para Facilitar a manipulação do ResponseWriter 80%
Desenvolver método para Facilitar a manipulação do Request 80%
Desenvolver suporte a ServeHTTP 100%
Desenvolver suporte a middlewares 100%
Desenvolver suporte a middleware compress 100%
Desenvolver suporte a middlewares cors 100%
Desenvolver suporte a middlewares logger 100%
Desenvolver suporte a middlewares maxbody 100%
Desenvolver suporte a middlewares msgid 100%
Desenvolver suporte a middlewares msguuid 100%
Desenvolve suporte Static Files 0.%
Desenvolver suporte Cors 100.%
Desenvolver suporte Cient Get 100.%
Desenvolver suporte Cient Post 100.%
Desenvolver suporte Cient Put 100.%
Desenvolver suporte Cient Delete 100.%
Desenvolver suporte Cient Fast Get 90.%
Desenvolver suporte Cient Fast Post 80.%
Desenvolver suporte Cient Fast Put 80.%
Desenvolver suporte Cient Fast Delete 80.%

Primeiro exemplo Quick

package main

import "github.com/jeffotoni/quick"

func main() {
    q := quick.New()

    q.Get("/v1/user", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).SendString("Quick em ação ❤️!")
    })

    q.Listen("0.0.0.0:8080")
}
$ curl -i -XGET -H "Content-Type:application/json" \
'localhost:8080/v1/user'
HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 22 Feb 2023 07:45:36 GMT
Content-Length: 23

Quick em ação ❤️!

Quick Get Params

package main

import "github.com/jeffotoni/quick"

func main() {
    q := quick.New()

    q.Get("/v1/customer/:param1/:param2", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")

        type my struct {
            Msg string `json:"msg"`
            Key string `json:"key"`
            Val string `json:"val"`
        }

        return c.Status(200).JSON(&my{
            Msg: "Quick ❤️",
            Key: c.Param("param1"),
            Val: c.Param("param2"),
        })
    })

    q.Listen("0.0.0.0:8080")
}
$ curl -i -XGET -H "Content-Type:application/json" \
'localhost:8080/v1/customer/val1/val2'
HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 22 Feb 2023 07:45:36 GMT
Content-Length: 23

{"msg":"Quick ❤️","key":"val1","val":"val2"}

Quick Post Body json

package main

import "github.com/jeffotoni/quick"

type My struct {
    Name string `json:"name"`
    Year int    `json:"year"`
}

func main() {
    q := quick.New()
    q.Post("/v1/user", func(c *quick.Ctx) error {
        var my My
        err := c.BodyParser(&my)
        if err != nil {
            return c.Status(400).SendString(err.Error())
        }

        return c.Status(200).String(c.BodyString())
        // ou 
        // c.Status(200).JSON(&my)
    })

    q.Listen("0.0.0.0:8080")
}
$ curl -i -XPOST -H "Content-Type:application/json" \
'localhost:8080/v1/user' \
-d '{"name":"jeffotoni", "year":1990}'
HTTP/1.1 200 OK
Date: Wed, 22 Feb 2023 08:10:06 GMT
Content-Length: 32
Content-Type: text/plain; charset=utf-8

{"name":"jeffotoni","year":1990}

🎛️| Funcionalidades

Funcionalidades Possui
🛣️ Gerenciador de Rotas sim
📁 Server Files Static sim
🚪 Grupo de Rotas sim
🌐 Middlewares sim
🚀 HTTP/2 support sim
🧬 Data binding for JSON, XML and form payload sim
🔍 Suporte para regex sim

📚| Examples

Este repositório contém exemplos práticos do Framework Quick, um framework web rápido e leve, desenvolvido em Go. Os exemplos estão organizados em pastas separadas, cada uma contendo um exemplo completo de uso do framework em uma aplicação web simples. Se você tem algum exemplo interessante de uso do Framework Quick, sinta-se à vontade para enviar uma solicitação de pull request com sua contribuição. O repositório de exemplos do Framework Quick pode ser encontrado em aqui.

Quick Post Bind json

package main

import "github.com/jeffotoni/quick"

type My struct {
    Name string `json:"name"`
    Year int    `json:"year"`
}

func main() {
    q := quick.New()
    q.Post("/v2/user", func(c *quick.Ctx) error {
        var my My
        err := c.Bind(&my)
        if err != nil {
            return c.Status(400).SendString(err.Error())
        }
        return c.Status(200).JSON(&my)
    })

    q.Listen("0.0.0.0:8080")
}
$ curl -i -XPOST -H "Content-Type:application/json" \
'localhost:8080/v2/user' \
-d '{"name":"Marcos", "year":1990}'
HTTP/1.1 200 OK
Date: Wed, 22 Feb 2023 08:10:06 GMT
Content-Length: 32
Content-Type: text/plain; charset=utf-8

{"name":"Marcos","year":1990}

Cors

package main

import (
    "github.com/jeffotoni/quick"
    "github.com/jeffotoni/quick/middleware/cors"
)

func main() {
    q := quick.New()
    q.Use(cors.New())

    q.Get("/v1/user", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).SendString("Quick em ação com Cors❤️!")
    })

    q.Listen("0.0.0.0:8080")
}

quick.New(quick.Config{})

package main

import "github.com/jeffotoni/quick"

func main() {
    q := quick.New(quick.Config{
        MaxBodySize: 5 * 1024 * 1024,
    })

    q.Get("/v1/user", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).SendString("Quick em ação com Cors❤️!")
    })

    q.Listen("0.0.0.0:8080")
}

quick.Group()

package main

import "github.com/jeffotoni/quick"

func main() {
    q := quick.New(quick.Config{
        MaxBodySize: 5 * 1024 * 1024,
    })

    v1 := q.Group("/v1")
    v1.Get("/user", func(c *quick.Ctx) error {
        return c.Status(200).SendString("[GET] [GROUP] /v1/user ok!!!")
    })
    v1.Post("/user", func(c *quick.Ctx) error {
        return c.Status(200).SendString("[POST] [GROUP] /v1/user ok!!!")
    })

    v2 := q.Group("/v2")
    v2.Get("/user", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).SendString("Quick em ação com [GET] /v2/user ❤️!")
    })

    v2.Post("/user", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).SendString("Quick em ação com [POST] /v2/user ❤️!")
    })

    q.Listen("0.0.0.0:8080")
}

Quick Tests

package main

import (
    "io"
    "strings"
    "testing"

    "github.com/jeffotoni/quick"
)

func TestQuickExample(t *testing.T) {

    // Here is a handler function Mock
    testSuccessMockHandler := func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        b, _ := io.ReadAll(c.Request.Body)
        resp := `"data":` + string(b)
        return c.Byte([]byte(resp))
    }

    q := quick.New()
    // Here you can create all routes that you want to test
    q.Post("/v1/user", testSuccessMockHandler)
    q.Post("/v1/user/:p1", testSuccessMockHandler)

    wantOutData := `"data":{"name":"jeff", "age":35}`
    reqBody := []byte(`{"name":"jeff", "age":35}`)
    reqHeaders := map[string]string{"Content-Type": "application/json"}

    data, err := q.QuickTest("POST", "/v1/user", reqHeaders, reqBody)
    if err != nil {
        t.Errorf("error: %v", err)
        return
    }

    s := strings.TrimSpace(data.BodyStr())
    if s != wantOutData {
        t.Errorf("was suppose to return %s and %s come", wantOutData, s)
        return
    }

    t.Logf("\nOutputBodyString -> %v", data.BodyStr())
    t.Logf("\nStatusCode -> %d", data.StatusCode())
    t.Logf("\nOutputBody -> %v", string(data.Body())) // I have converted in this example to string but comes []byte as default
    t.Logf("\nResponse -> %v", data.Response())
}

quick.regex

package main

import (
    "github.com/jeffotoni/quick"
    "github.com/jeffotoni/quick/middleware/msgid"
)

func main() {
    q := quick.New()

    q.Use(msgid.New())

    q.Get("/v1/user/{id:[0-9]+}", func(c *quick.Ctx) error {
        c.Set("Content-Type", "application/json")
        return c.Status(200).String("Quick ação total!!!")
    })

    q.Listen("0.0.0.0:8080")
}

🤝| Contribuições

Já temos diversos exemplos, e já podemos testar e brincar 😁. É claro, estamos no início, ainda tem muito para fazer. Fiquem à vontade em fazer PR (com risco de ganhar uma camiseta Go ❤️ e claro reconhecimento como profissional Go 😍 no mercado de trabalho).

🚀 Apoiadores do Projeto Quick 🙏

O Projeto Quick visa desenvolver e disponibilizar softwares de qualidade para a comunidade de desenvolvedores. 💻 Para continuarmos a melhorar nossas ferramentas, contamos com o apoio de nossos patrocinadores no Patreon. 🤝

Agradecemos a todos os nossos apoiadores! 🙌 Se você também acredita em nosso trabalho e quer contribuir para o avanço da comunidade de desenvolvimento, considere apoiar o Projeto Quick em nosso Patreon aqui

Juntos podemos continuar a construir ferramentas incríveis! 🚀

Avatar User Donation
@jeffotoni x 10
@Crow3442 x 5
@Guilherme-De-Marchi x 5

quick's People

Contributors

crow3442 avatar davisbento avatar guilherme-s3wf avatar guilhermecaruso avatar jeffotoni avatar marcos-dev88 avatar victorfernandesraton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

quick's Issues

Função/Método Static - hospedar páginas staticas

instalar o gosec:
https://github.com/securego/gosec

$ gosec ./...

Para funcionar o static tomar cuidado porque ele irá servir a página e podemos avançar para 2 modelos um modelo é hospedar a página com html, js, img tudo fisico no disco porém com binario go.

Modelo 2 implementar embed ou seja html, css, js e img dentro do binário sem haver necessidade de enviar arquivos para hospedar tudo fica no binário.

Examples:
https://github.com/jeffotoni/goexample/tree/master/embed

Bug - GET Params

Atualmente estamos tendo um erro ao pegar os parâmetros na request após dos definidos.

exemplo:

working: /api/:msgID

Not Working: /api/:msg/some

Não está pegando os parametros como values para

app.Get("/v1/customer/:param1/:param2", func(c *quick.Ctx) error {
c.Set("Content-Type", "application/json")

	type my struct {
		Msg string `json:"msg"`
		Key string `json:"key"`
		Val string `json:"val"`
	}

	return c.Status(200).JSON(&my{
		Msg: "Quick ❤️",
		Key: c.Param("param1"),
		Val: c.Param("param2"),
	})
})

curl -i -XGET localhost:8080/v1/customer/val1/val2
{"msg":"Quick ❤️","key":"","val":""}

Benchmarking - Quick

Vamos fazer Benchmarking dos métodos todos eles exemplo: app.New(), app.Post(), app.Get(), app.Put(), app.Delete(), c.BodyParser(), c.Bind(), app.Group etc..

Mapear os gargalos e checar os Benchmarking para vermos o desempenho

Cors

O cors precisa ser passado no Listen:

server := &http.Server{
Addr: addr,
Handler: cors,
}

infelizmente, então teremos que implementar algo mais inteligente e nativo, o cors é uma EXCEÇÃO dos middlewares.

image

k6 para test de stress

Vamos montar nossos scripts de testes de stress no k6 lá no REPO EXEMPLOS:
https://github.com/gojeffotoni/examples

Vamos fazer teste para posts com json de: 1k, 5k, 10k, 50k, 100k, 200k, 300k, 500k, 1, 2, 3, 5 , 10 15, 20Mb,

Vamos pegar os resultados e publicar a nível de gráfico no README exemplos e no quick.

CORS - BUG INTEGRAÇÃO

Cors -> nativo em nosso ambiente middleware
Cors -> não nativo externo atribuindo a rota ( FOCAR NESTE )

c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})

mux := http.NewServeMux()

mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte("{\"hello\": \"world\"}"))
})

n := negroni.Classic()
n.Use(c)
n.UseHandler(mux)
n.Run(":3000")

Example:
https://github.com/rs/cors/blob/master/examples/negroni/server.go

Atualizações no Body, Bind e Response - CORREÇÃO para executar na chamada do MÉTODO

Atualizações no Body, Bind e Response -
- CORREÇÃO para executar na chamada do MÉTODO

Body() -> retornará byte -> e só poderá ser executado depois de um BodyParser sem ele vc não tem bytes ..

Bind(&myInterface) -> é um json.NewDecoder então não temos os bytes , e a função Body() irá fazer json.Marshal do objeto então só poderá ser feito depois do Bind()

BodyParse(&myInterface) -> é um io.ReadAll nele já temos Byte do Body()

Request caindo em handler errado quando se tem um GET com path params

Quando se cria mais de uma rota GET, sendo uma com path params, todas as requests com esse método estão sendo forçadas para a request que espera os params. Vou exemplificar:

No exemplo abaixo, temos duas rotas GET, sendo uma delas com pathParams:

package main

import (
	"log"
	"net/http"

	"github.com/jeffotoni/quick"
)

func main() {
	app := quick.New()

	app.Use(func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//This is the first middleware! This guy generate a msgID
			r.Header.Set("Messageid", "12345")
			h.ServeHTTP(w, r)
		})
	})

	app.Get("/v1/customer/:param1/:param2", func(c *quick.Ctx) {
		c.Set("Content-Type", "application/json")

		type my struct {
			Msg string `json:"msg"`
			Key string `json:"key"`
			Val string `json:"val"`
		}

		log.Println(c.Headers["Messageid"])

		c.Status(200).Json(&my{
			Msg: "Quick ❤️",
			Key: c.Param("param1"),
			Val: c.Param("param2"),
		})
	})

	app.Use(func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//This is the third middleware! This guy blocks request if header contains Block == true
			if r.Header.Get("Block") == "" {
				w.WriteHeader(400)
				w.Write([]byte(`"Message": "send the block header, please! :("`))
				return
			}

			if r.Header.Get("Block") == "true" {
				w.WriteHeader(200)
				w.Write([]byte(`"Message": "quicks block this request :)"`))
				return
			}

			r.Header.Set("Messageid", "12345")
			h.ServeHTTP(w, r)
		})
	})

	app.Get("/v1/blocked", func(c *quick.Ctx) {
		c.Set("Content-Type", "application/json")

		type my struct {
			Msg   string `json:"msg"`
			Block string `json:"block_message"`
		}

		log.Println(c.Headers["Messageid"])

		c.Status(200).Json(&my{
			Msg:   "Quick ❤️",
			Block: c.Headers["Block"][0],
		})
	})

	log.Fatal(app.Listen("0.0.0.0:8080"))
}

Nesse caso, todas as requisições GET feitas a aplicação sempre caem na rota /v1/customer/:param1/:param2. Exemplo:

Esse caso era para cair na rota /v1/blocked

curl -iv -H "Block: false" localhost:8080/v1/blocked     
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /v1/blocked HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
> Block: false
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: application/json
Content-Type: application/json
< Date: Wed, 22 Feb 2023 19:19:39 GMT
Date: Wed, 22 Feb 2023 19:19:39 GMT
< Content-Length: 49
Content-Length: 49

< 
* Connection #0 to host localhost left intact
{"msg":"Quick ❤️","key":"v1","val":"blocked"}% 

Esse caso era para dar um erro de Not Found já que a rota não foi declarada

curl -iv -H "Block: false" localhost:8080/look/error
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /look/error HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
> Block: false
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: application/json
Content-Type: application/json
< Date: Wed, 22 Feb 2023 19:21:04 GMT
Date: Wed, 22 Feb 2023 19:21:04 GMT
< Content-Length: 49
Content-Length: 49

< 
* Connection #0 to host localhost left intact
{"msg":"Quick ❤️","key":"look","val":"error"}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.