package for building REST-style Web Services using Go

go-restful

package for building REST-style Web Services using Google Go

Build Status Go Report Card GoDoc codecov

REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:

  • GET = Retrieve a representation of a resource
  • POST = Create if you are sending content to the server to create a subordinate of the specified resource collection, using some server-side algorithm.
  • PUT = Create if you are sending the full content of the specified resource (URI).
  • PUT = Update if you are updating the full content of the specified resource.
  • DELETE = Delete if you are requesting the server to delete the resource
  • PATCH = Update partial content of a resource
  • OPTIONS = Get information about the communication options for the request URI

Usage

Using Go Modules

As of version v3.0.0 (on the v3 branch), this package supports Go modules.

import (
	restful "github.com/emicklei/go-restful/v3"
)

Without Go Modules

All versions up to v2.*.* (on the master) are not supporting Go modules.

import (
	restful "github.com/emicklei/go-restful"
)

Example

ws := new(restful.WebService)
ws.
	Path("/users").
	Consumes(restful.MIME_XML, restful.MIME_JSON).
	Produces(restful.MIME_JSON, restful.MIME_XML)

ws.Route(ws.GET("/{user-id}").To(u.findUser).
	Doc("get a user").
	Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
	Writes(User{}))		
...
	
func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
	id := request.PathParameter("user-id")
	...
}

Full API of a UserResource

Features

  • Routes for request → function mapping with path parameter (e.g. {id} but also prefix_{var} and {var}_suffix) support
  • Configurable router:
    • (default) Fast routing algorithm that allows static elements, google custom method, regular expressions and dynamic parameters in the URL path (e.g. /resource/name:customVerb, /meetings/{id} or /static/{subpath:*})
    • Routing algorithm after JSR311 that is implemented using (but does not accept) regular expressions
  • Request API for reading structs from JSON/XML and accesing parameters (path,query,header)
  • Response API for writing structs to JSON/XML and setting headers
  • Customizable encoding using EntityReaderWriter registration
  • Filters for intercepting the request → response flow on Service or Route level
  • Request-scoped variables using attributes
  • Containers for WebServices on different HTTP endpoints
  • Content encoding (gzip,deflate) of request and response payloads
  • Automatic responses on OPTIONS (using a filter)
  • Automatic CORS request handling (using a filter)
  • API declaration for Swagger UI (go-restful-openapi, see go-restful-swagger12)
  • Panic recovery to produce HTTP 500, customizable using RecoverHandler(...)
  • Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...)
  • Configurable (trace) logging
  • Customizable gzip/deflate readers and writers using CompressorProvider registration

How to customize

There are several hooks to customize the behavior of the go-restful package.

  • Router algorithm
  • Panic recovery
  • JSON decoder
  • Trace logging
  • Compression
  • Encoders for other serializers
  • Use jsoniter by build this package using a tag, e.g. go build -tags=jsoniter .

TODO: write examples of these.

Resources

Type git shortlog -s for a full list of contributors.

© 2012 - 2020, http://ernestmicklei.com. MIT License. Contributions are welcome.

Owner
Ernest Micklei
GCP Architect, Software Engineer, Google Developer Expert, Gopher, Dartian, Javanian, Smalltalker
Ernest Micklei
Comments
  • Go module support

    Go module support

    hi,

    i know that vgo is not released. but it would be great to support it in the near future. with the current version of vgo you cannot import a version-2 of go-restful. the design document says:

    Again, the go.mod file is required for v2 and later so that vgo can use the module line as a sign that the code has been written with semantic import versioning in mind, ...

    to support multiple versions, the packages should have the version in their import path (.../v2).

    so the author of vgo want the version 2 (or later versions) to have a go.mod file. this is not present in the current code. this leads to the following situation:

    $ vgo list -t github.com/emicklei/go-restful   
    github.com/emicklei/go-restful
            v1.0.0
            v1.0.1
            v1.1.0
            v1.1.1
            v1.1.2
            v1.1.3
    

    Great!

    $ vgo list -t github.com/emicklei/go-restful/v2
    github.com/emicklei/go-restful/v2
            v2.2.1
            v2.3.0
            v2.4.0
            v2.5.0
            v2.6.0
            v2.6.1
            v2.7.0
    

    Great!

    But:

    $ vgo get github.com/emicklei/go-restful/v2       
    vgo: finding github.com/emicklei/go-restful/v2 v2.7.0
    vgo: github.com/emicklei/go-restful/v2 v2.7.0: missing go.mod
    vgo: finding github.com/emicklei/go-restful/v2 v2.7.0
    vgo: github.com/emicklei/go-restful/v2 v2.7.0: missing go.mod
    vgo get: missing go.mod
    

    :-( Here vgo complains about the missing go.mod file which indicates that the module does semantic versioning.

    So adding a dependency with vgo:

    $ vgo get github.com/emicklei/[email protected] 
    $ vgo list -m
    github.com/cznic/fileutil             v0.0.0-20180108211300-6a051e75936f
    github.com/emicklei/go-restful        v0.0.0-20180416204930-2810ccc68e0c
    github.com/go-stack/stack             v1.7.0
    ...
    

    as you can see, go-restful is added as an unversioned dependency (0.0.0) with the current git-SHA (2810ccc68e0c). well, this works, but is is not the desired behaviour (at least for me).

    It would be great to support vgo in the long run. at the moment i have no problem with the 0.0.0 dependency but it would be great to support vgo in some later versions.

  • restful v2

    restful v2

    The idea is to start a new repository (but keeping the package name) that will introduce a new, improved, API to create REST-like applications in Go. With respect to the current status, this will be a major change (hence the v2) as I expect to see a few changes to the current API.

    This issue will list the things I like to change/improve

    • move Swagger to its own repository allowing for a 2.0 OpenAPI support
    • RouteFunction will have a Context parameter (as the last?)
    • Replace public vars by functions
    • Use CurlyRouter by default
    • No caching of request content by default
    • Introduce a static container in addition to the current one that allows add/remove WebServices
    • Remove request attributes in favor of Context

    Other suggestions are welcome.

  • Nested structs not returned in swagger output

    Nested structs not returned in swagger output

    I have a common response object that is returned on all my rest methods. Depending on the resource different parts of it is filled out. This use case doesnt work very well with swagger, only the container object is returned in the swagger model list and not the sub-structs.

    Here is an example: https://gist.github.com/viblo/7409083

  • How to detect if a connection is still pending

    How to detect if a connection is still pending

    Hi,

    I have a route handler that is asking as a long pool end. Basically I wait for a new message to come in on a channel and when that happens, I send this message as part of the response to the http request originated on a page using ajax.

    This works pretty well, but now I need a way to detect if the the browser is still waiting for the response, or if the browser moved on to another page.

    What happens now is that go-restful tries to send the response, but as there is no http connection listening, I kind of lose the message.

    If there is a way to detect that there is no more an http connection, I could simply resend the message to the channel I use, so that the next request will get it.

    (I hope it makes sense, I can post the code I have so far if that will help you)

    Thanks

    Diego

  • [security] Path parser inconsistency could lead to bypass several security checks in emicklei/go-restful

    [security] Path parser inconsistency could lead to bypass several security checks in emicklei/go-restful

    Reported via huntr.dev here.

    Created: May 28th 2022

    Description

    There is a inconsistency between how golang(and other packages) and go-restful parses url path. This incosistency could lead several security check bypass in a complex system.

    Steps to reproduce

    Copy and run the code below

    package main
    
    import (
        "fmt"
        "html"
        "log"
        "net/http"
    )
    
    func main() {
    
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
        })
    
    // If a user request matches with this path then it will be checked and if it didn't match then the request will be directly forwarded to the go-restful server.
        http.HandleFunc("/users/id_will_be_here", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "I'm checking if the user is authorized to see this user info. If he is authorized then I will forward this request to the go-restful server which will return the user info")
        })
    
        log.Fatal(http.ListenAndServe(":8081", nil))
    
    }
    

    Now If you send a request to the http://localhost:8081/users/id_will_be_here then you will get a hit to the expected endpoint and it will check the authorization part Now if you send a request to the http://localhost:8081/users/id_will_be_here/ (notice the extra / in last) then this server won't process this request as the path name doesn't match but the problem is that go-restful treat this path and the previous as same. So this inconsistency could lead some issues in this scenerio as the first sever wont check the security checks but the second server(go-restful) will return user data.

    Impact

    Security check bypass

    Occurrences

    web_service.go L80

  • Can't build the code

    Can't build the code

    I'm trying to test out your framework for use with a Go based Google App Engine app but can't get past step 1. When I issue a command

    go get github.com/emicklei/go-restful

    It pulls it in and spews out several errors:

    github.com/emicklei/go-restful

    src/github.com/emicklei/go-restful/container.go:67: method c.dispatch is not an expression, must be called src/github.com/emicklei/go-restful/container.go:79: method c.dispatch is not an expression, must be called src/github.com/emicklei/go-restful/container.go:81: method c.dispatch is not an expression, must be called src/github.com/emicklei/go-restful/curly.go:49: undefined: sort.Reverse src/github.com/emicklei/go-restful/jsr311.go:109: undefined: sort.Reverse src/github.com/emicklei/go-restful/jsr311.go:136: undefined: sort.Reverse src/github.com/emicklei/go-restful/options_filter.go:21: method DefaultContainer.OPTIONSFilter is not an expression, must be called src/github.com/emicklei/go-restful/request.go:48: r.Request.PostFormValue undefined (type *http.Request has no field or method PostFormValue)

    Am I doing it wrong? I'm pretty new to Go and this is the first package outside the standard ones I am trying to use...

    I'd like to kick off using this for a large project I am planning, so appreciate any assistance you can provide.

    p.s. I found the fork by Moddus - but it does exactly the same thing.

  • Produces(restful.MIME_JSON) Not Returning

    Produces(restful.MIME_JSON) Not Returning "application/json" as Content-Type

    I've been using go-restful for a few weeks and so far have been really impressed. I'm having one issue that I can not figure out. (Go newbie here)

    I have created a WebService specifying it Consumes and Produces JSON, however the response I receive from the server has the Content-Type as "text/plain".

    I have read and re-read the documentation and can't solve this issue. I have tried adding an Accept header to the Request but "text/plain" is still returned. The documentation seems implies that if Produces set to only product JSON all responses from the server will have the Content-Type as "application/json"

    Any ideas how to solve this issue?

    ws := new(restful.WebService)
            ws.Path("/internal")
            ws.Consumes(restful.MIME_JSON)
            ws.Produces(restful.MIME_JSON)
    
            ws.Route(ws.GET("/category/{user_id}").To(r.getCategories).
                    Doc("Return available categories").
                    Param(ws.PathParameter("user_id", "Id of user").Required(true)).
                    Writes(model.ApiResponse{}))
    

    My handler function return the results as follows.

    func (r MyResource) getCategories(req *restful.Request, resp *restful.Response) {
            ...
            resp.WriteHeader(http.StatusOK)
            resp.WriteAsJson(data)
            return
    }
    
  • Proposed addition of 'type' tag for swagger

    Proposed addition of 'type' tag for swagger

    Currently I have some struct fields that are essentially a type alias for an integer. They do not show up in my swagger documentation when I pass them to Reads(), they are omitted entirely. In the long term, it might be nice for the reflection magic in the swagger model_builder etc could detect these and handle them as though they were the appropriate type. Implementing a MarshalJSON method on my aliased type did get them to show up in the swagger documentation, but always as type "string" versus integer. This PR is much less ambitious than a fix for the above, but could prove generically useful in the event that we ever wanted to override the type that was guessed.

  • New method like `Response.WriteHeader` (respects content types in `Produces`)

    New method like `Response.WriteHeader` (respects content types in `Produces`)

    Method WriteHeader doesn't check Produces defined in Route / Path. Before 14 Sep headers was set in WriteEntity, because WriteHeader just set status code.

  • FilterChain should pass the request and response from filters to Target function

    FilterChain should pass the request and response from filters to Target function

    The PR #478 brought some weird changes that breaks the filters behaviour. We have a filter that creates another instance of Response to intercept all headers and data, then does an audit and modifies the data and only then it forwards to the original response. But the lambda added in that PR breaks this logic, since the target function writes directly to the original response.

  • Documentation: HTTP status codes

    Documentation: HTTP status codes

    Is there a way to have HTTP status codes in the (swagger) documentation? I figured there's ResponseMessages but not sure how to use since I haven't found anything in web_service.go

    I'd like to document the possible HTTP status codes, like 200, 201, 405 etc

    thanks

  • Tokenizer change in 3.10 breaks many URLs

    Tokenizer change in 3.10 breaks many URLs

    I'm using https://github.com/emicklei/go-restful/tree/67c9f7e97871832a5773f8a7c66230c7e3322e20/examples/openapi as the test case.

    This has the following content in go.mod:

    module github.com/emicklei/go-restful/examples/openapi
    
    go 1.14
    
    require (
            github.com/emicklei/go-restful-openapi/v2 v2.8.0
            github.com/emicklei/go-restful/v3 v3.8.0
            github.com/go-openapi/spec v0.20.4
    )
    

    Running this:

    ❯ go install
    
    ❯ go run ./restful-openapi.go
    2022/11/13 21:18:05 Get the API using http://localhost:8080/apidocs.json
    2022/11/13 21:18:05 Open Swagger UI using http://localhost:8080/apidocs/?url=http://localhost:8080/apidocs.json
    

    And in a second window:

    ❯ curl --silent -D - http://localhost:8080/apidocs.json | head -10
    HTTP/1.1 200 OK
    Content-Type: application/json
    Date: Sun, 13 Nov 2022 20:20:57 GMT
    Transfer-Encoding: chunked
    
    {
     "swagger": "2.0",
     "info": {
      "description": "Resource for managing Users",
      "title": "UserService",
    

    Upgraded to github.com/emicklei/go-restful/v3 v3.9.0:

    ❯ go get github.com/emicklei/go-restful/[email protected]
    go: upgraded github.com/emicklei/go-restful/v3 v3.8.0 => v3.9.0
    
    ❯ go run ./restful-openapi.go
    2022/11/13 21:21:25 Get the API using http://localhost:8080/apidocs.json
    2022/11/13 21:21:25 Open Swagger UI using http://localhost:8080/apidocs/?url=http://localhost:8080/apidocs.json
    

    Still good:

    ❯ curl --silent -D - http://localhost:8080/apidocs.json | head -10
    HTTP/1.1 200 OK
    Content-Type: application/json
    Date: Sun, 13 Nov 2022 20:21:48 GMT
    Transfer-Encoding: chunked
    
    {
     "swagger": "2.0",
     "info": {
      "description": "Resource for managing Users",
      "title": "UserService",
    

    But with 3.10:

    ❯ go get github.com/emicklei/go-restful/[email protected]
    go: upgraded github.com/emicklei/go-restful/v3 v3.9.0 => v3.10.0
    
    ❯ go run ./restful-openapi.go
    2022/11/13 21:22:09 Get the API using http://localhost:8080/apidocs.json
    2022/11/13 21:22:09 Open Swagger UI using http://localhost:8080/apidocs/?url=http://localhost:8080/apidocs.json
    

    It fails:

    ❯ curl --silent -D - http://localhost:8080/apidocs.json | head -10
    HTTP/1.1 404 Not Found
    Date: Sun, 13 Nov 2022 20:22:20 GMT
    Content-Length: 19
    Content-Type: text/plain; charset=utf-8
    
    404: Page Not Found
    

    Instead it suddenly requires a trailing slash:

    ❯ curl --silent -D - http://localhost:8080/apidocs.json/ | head -10
    HTTP/1.1 200 OK
    Content-Type: application/json
    Date: Sun, 13 Nov 2022 20:22:50 GMT
    Transfer-Encoding: chunked
    
    {
     "swagger": "2.0",
     "info": {
      "description": "Resource for managing Users",
      "title": "UserService",
    

    This is a breaking change that I did not expect in a stable release… And besides, the URL became ugly :)

Provide open, community driven reusable components for building distributed applications

Components Contrib The purpose of Components Contrib is to provide open, community driven reusable components for building distributed applications. T

Nov 28, 2021
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Jan 5, 2023
Golanger Web Framework is a lightweight framework for writing web applications in Go.

/* Copyright 2013 Golanger.com. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except

Nov 14, 2022
Web framework for creating apps using Go in Google AppEngine

Welcome to app.go v3.0 app.go is a simple web framework for use in Google AppEngine. Just copy the app folder to your working folder and import it fro

Mar 21, 2021
A small and evil REST framework for Go

go-rest A small and evil REST framework for Go Reflection, Go structs, and JSON marshalling FTW! go get github.com/ungerik/go-rest import "github.com/

Dec 6, 2022
🍐 Elegant Golang REST API Framework
🍐 Elegant Golang REST API Framework

An Elegant Golang Web Framework Goyave is a progressive and accessible web application framework focused on REST APIs, aimed at making backend develop

Jan 4, 2023
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Jan 9, 2023
An idiomatic Go REST API starter kit (boilerplate) following the SOLID principles and Clean Architecture

Go RESTful API Starter Kit (Boilerplate) This starter kit is designed to get you up and running with a project structure optimized for developing REST

Jan 3, 2023
:bullettrain_side: High-performance web server for Go.
:bullettrain_side: High-performance web server for Go.

Aero is a high-performance web server with a clean API. Installation go get -u github.com/aerogo/aero/... Usage Run this in an empty directory: aero -

Dec 8, 2022
An ideally refined web framework for Go.

Air An ideally refined web framework for Go. High-performance? Fastest? Almost all web frameworks are using these words to tell people that they are t

Dec 15, 2022
Eudore is the core of a golang lightweight web framework.

Eudore eudore是一个golang轻量级web框架核心,可以轻松扩展成一个技术栈专用框架,具有完整框架设计体系。 反馈和交流请加群组:QQ群373278915。 Features 易扩展:主要设计目标、核心全部解耦,接口即为逻辑。 简单:对象语义明确,框架代码量少复杂度低,无依赖库。 易用

Nov 7, 2022
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin Web Framework Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks

Jan 2, 2023
Goal is a toolkit for high productivity web development in Go language in the spirit of Revel Framework that is built around the concept of code generation.

Goal Goal is a set of tools for high productivity web development in Go language. Goal, being mostly inspired by Revel Framework and its discussions,

Sep 27, 2021
a golang web mvc framework, like asp.net mvc.

goku goku is a Web Mvc Framework for golang, mostly like ASP.NET MVC. doc & api Installation To install goku, simply run go get github.com/QLeelulu/go

Dec 7, 2022
A high level web-framework for Go

go-start is a high level web-framework for Go, like Django for Python or Rails for Ruby. Installation: go get github.com/ungerik/go-start Documentatio

Dec 24, 2022
A lightweight RESTful web framework for Go
A lightweight RESTful web framework for Go

Goweb A lightweight RESTful web framework for Go. For examples and usage, please read the Goweb API Documentation Read our Articles Who uses Goweb? "U

Dec 12, 2022
Fast and Reliable Golang Web Framework
Fast and Reliable Golang Web Framework

Gramework The Good Framework Gramework long-term testing stand metrics screenshot made with Gramework Stats Dashboard and metrics middleware What is i

Dec 18, 2022
Mango is a modular web-application framework for Go, inspired by Rack, and PEP333.

Mango Mango is a modular web-application framework for Go, inspired by Rack and PEP333. Note: Not actively maintained. Overview Mango is most of all a

Nov 17, 2022
Classy web framework for Go

Martini NOTE: The martini framework is no longer maintained. Martini is a powerful package for quickly writing modular web applications/services in Go

Dec 29, 2022