Giter Club home page Giter Club logo

osin's Introduction

OSIN

GoDoc

Golang OAuth2 server library

OSIN is an OAuth2 server library for the Go language, as specified at http://tools.ietf.org/html/rfc6749 and http://tools.ietf.org/html/draft-ietf-oauth-v2-10.

It also includes support for PKCE, as specified at https://tools.ietf.org/html/rfc7636, which increases security for code-exchange flows for public OAuth clients.

Using it, you can build your own OAuth2 authentication service.

The library implements the majority of the specification, like authorization and token endpoints, and authorization code, implicit, resource owner and client credentials grant types.

Example Server

import (
	"github.com/openshift/osin"
	ex "github.com/openshift/osin/example"
)

// ex.NewTestStorage implements the "osin.Storage" interface
server := osin.NewServer(osin.NewServerConfig(), ex.NewTestStorage())

// Authorization code endpoint
http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
	resp := server.NewResponse()
	defer resp.Close()

	if ar := server.HandleAuthorizeRequest(resp, r); ar != nil {

		// HANDLE LOGIN PAGE HERE

		ar.Authorized = true
		server.FinishAuthorizeRequest(resp, r, ar)
	}
	osin.OutputJSON(resp, w, r)
})

// Access token endpoint
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
	resp := server.NewResponse()
	defer resp.Close()

	if ar := server.HandleAccessRequest(resp, r); ar != nil {
		ar.Authorized = true
		server.FinishAccessRequest(resp, r, ar)
	}
	osin.OutputJSON(resp, w, r)
})

http.ListenAndServe(":14000", nil)

Example Access

Open in your web browser:

http://localhost:14000/authorize?response_type=code&client_id=1234&redirect_uri=http%3A%2F%2Flocalhost%3A14000%2Fappauth%2Fcode

Storage backends

There is a mock available at example/teststorage.go which you can use as a guide for writing your own.

You might want to check out other implementations for common database management systems as well:

License

The code is licensed using "New BSD" license.

Author

Rangel Reale [email protected]

Changes

2019-05-13

  • NON-BREAKING CHANGES
    • Updated imports in examples to use github.com/openshift/osin instead of github.com/RangelReale/osin

2014-06-25

  • BREAKING CHANGES:
    • Storage interface has 2 new methods, Clone and Close, to better support storages that need to clone / close in each connection (mgo)

    • Client was changed to be an interface instead of an struct. Because of that, the Storage interface also had to change, as interface is already a pointer.

    • HOW TO FIX YOUR CODE:

      • In your Storage, add a Clone function returning itself, and a do nothing Close.

      • In your Storage, replace all *osin.Client with osin.Client (remove the pointer reference)

      • If you used the osin.Client struct directly in your code, change it to osin.DefaultClient, which is a struct with the same fields that implements the interface.

      • Change all accesses using osin.Client to use the methods instead of the fields directly.

      • You MUST defer Response.Close in all your http handlers, otherwise some Storages may not clean correctly.

          resp := server.NewResponse()
          defer resp.Close()
        

osin's People

Contributors

a13xb avatar agtorre avatar ahmet avatar albertoleal avatar andrewhare avatar aodin avatar arjunrn avatar brahmasmi avatar burnto avatar bvwells avatar darh avatar deads2k avatar denouche avatar dratner avatar elgris avatar ericchiang avatar felipeweb avatar fyb3roptik avatar hatchan avatar joeshaw avatar liggitt avatar michael-k avatar openshift-merge-robot avatar rakesh-eltropy avatar rangelreale avatar rootatdarkstar avatar stlaz avatar swenson avatar vgarvardt avatar yookoala 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  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  avatar  avatar

Watchers

 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

osin's Issues

testcases needed?

Consider adding testcases to the code.

Without this, it does not inspire confidence for people to use it.

examples broken

For example, jwttoken example broken with error: "Error Request must be POST".

Persistent login with the Implicit grant

Hi there,
I have a web app that uses osin for login. It uses https://github.com/andreassolberg/jso (Implicit flow).

I need to implement "Remember me" feature on the login page and the idea is to prolong the ttl of the token if it's requested by the user.

Now the AccessData::ExpiresIn parameter is by default 3600.
Can we create a special parameter Persistant or a convention ExpiresIn==-1 that will tell OSIN not to expire the token?

Thanks

Don't delete access+refresh tokens on refresh_token flow

Mobile devices with potential connectivity issues may request a refresh_token grant type without being able to accept the response,
in such case, the refresh token is removed and the mobile device has to authenticate the user again using another flow.

we experienced this issue during QA of bad connectivity.

I suggest to keep the refresh + access token even on successful refresh and let the server handle deletion (such as within the first usage of the new token), or on storage.LoadAccess() for the new token.

I'm already doing this in a fork and can submit a PR.

Client secret required for password grant type

Reading through RFC (4.3) I could not find a clear and direct statement about client secret -- is it optional or required. OSIN makes it required (judging by logic in getClientAuth()) but changing that and make this configurable would be trivial.

I havn't done any extensive research, but for example, PHP's implementation (https://github.com/bshaffer/oauth2-server-php) allows client secrets to be optional. A few other examples: http://security.stackexchange.com/questions/64091/oauth2-resource-owner-password-credentials-grant, https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#web-server-apps

My opinion is that both functions, CheckBasicAuth() and getClientAuth() take too much responsibility in validating of the credentials. This should be responsibility of some other (pluggable) function (similar as ClientSecretMatcher solution)

Any thoughts on that?

Code grant types

Hello, i want to integrate your framework in my project.
Could you tell me, which access token grant types are supported right now from Oauth 2.0 specification?

Invalid Grant when handleAuthorizationCodeRequest is called

For some reason, when attempting to access the token URL generated by the app, I get an invalid_grant error triggered in access.go line 181, right after loading authorized data from the provided code.

This doesn't happen all the time. When I restart my goapp server it accesses the token fine after refreshing the web page once. I really want to be able to download this token after the url is generated however this inconsistency is blocking me.

This is how I download the token:

    ctx := appengine.NewContext(r)
    client := urlfetch.Client(ctx)
    req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:8080%s", aurl), nil)
    if err != nil {
        w.Write([]byte("error forming req"))
    }
    ba := &osin.BasicAuth{"<client username>", "<client password>"}
    req.SetBasicAuth(ba.Username, ba.Password)
    res, err2 := client.Do(req)
    defer res.Body.Close()
    if err2 != nil {
        w.Write([]byte("error forming res"))
    }
    jdec := json.NewDecoder(res.Body)
    jdec.Decode(&jr)

^that only works sometimes as mentioned before. Can anyone please help? I've been stuck on this for days :(

go get failed with tokengen problem

My travis build (which depends on osin) failed today with the following message:

...
...

- go get -u github.com/RangelReale/osin

../../RangelReale/osin/tokengen.go:31: not enough arguments to return

The command "go get -u github.com/RangelReale/osin" failed and exited with 2 during .

Seems something is wrong with the recent commits.

JWT Bearer Flow

Do you plan to support the JWT bearer as described in RFC7523? Or do you have any pointers how to implement such?

Support for encrypted storage of passwords

Hi!

Am I missing something or are the passwords stored in plain text in the storages? It looks to me that all passwords are matched against their unencrypted dito. Are there any planned feature improvements on this or are you open for pull requests?

Nested AccessData when using refresh tokens

I notice the AccessData struct keep the previous AccessData record:

type AccessData struct {
....
AccessData *AccessData
....
}

The problem is when I use refresh_token grant type to create new access_tokens; it will save previous AccessData record in the pointer. So if I keep continue to use refresh_token multiple times, consequently I get something like that (I use mongo as storage for the access token)

{
"_id": "Y2MzNTE0ZTItODYyNy00YWY1LWJmMWUtNmRiYTRiODI5OWIy",
"client": {
"id": "1234",
"secret": "aabbccdd",
...
},
"authorizedata": null,
"accessdata": {
"client": {
"id": "1234",
"secret": "aabbccdd",
...
},
"authorizedata": null,
"accessdata": {
"client": {
"id": "1234",
"secret": "aabbccdd",
....
},
"authorizedata": {
....
},
.....
},
....
},
....
},
...
}

Beside the storage problem (the data for that entry might grow exceed the allowed entry size restricted by mongoDB), it also has problem when I unmarshal the json to struct; It's due to the 'Breaking Change' when client now is an interface not struct.

I take a look at the code. Seems that the AccessData not even being used. The GenerateAccessToken(data *AccessData, generaterefresh bool) (accesstoken string, refreshtoken string, err error) only use it in case of JWT token (base64 not being used). But still clientInfo (data.Client.GetId() -- in JWT GenerateAccessToken) can be obtain from the first level of the struct directly. I am wondering why we need to keep the previous Access Data pointer. If it's necessary, can I just keep at most 2 levels instead of infinitely nesting the object in.

refresh token expiration

This may be a misunderstanding of mine with the OAuth spec. I was under the impression that when requesting a refresh token, the new expiration would be a much longer duration. However in osin it just defaults to the same expiration as the access token. What would be the correct process for getting a token with a much longer expiration time?

Transport method other than HTTP

While trying to draft up my OAuth Server using this amazing library I've ran into a little bit of an issue. I'm not quite sure whether its by design or if you are open to possibly some API changes.

I'm developing some services using a micro service approach and would love to have an authentication service. Doing so I would like to use RPC as the communication layer. Sadly osin makes some pretty hard assumptions on using HTTP as the transport layer and doesn't seem to expose any sort of underlying API to support any other transport layer.

Would you be opposed to some API changes to accommodate other transport protocols? If so, would you ever consider splitting packages and exposing the HTTP api in a package say osin/http?

Find a way around UserData interface{}

First of all, thanks for this library, as it saved me a lot of time.

However i felt bad using AuthorizeRequest, AccessRequest and AuthorizeData's UserData interface{} field.

I used it to store info gathered during the authorization request and translate it into a JSON Web token after the access request.

I open this issue as a discussion, in the hope of a new solution to pass data between the storage and the api that dosen't involve an interface{} field.

Extend OSIN to support JSON web token (JWT) grant

Since JWT grant stills not standartised, it would be a good idea to implement this grant type, so we can use it to pass the client credentials in a much more secure way than passing directly inside HTTP form.

Endpoint example?

Thanks for creating this library. I'm new to oauth2 as well as to Go, so thanks for your patience. Is there an example of how to write an endpoint for it that's oauth protected? (I've got osin integrated with my app so I can generate tokens, but I'm not sure if I'm on my own to validate the headers, etc. on my actual functional endpoints.)

redirect_url vs redirect_uri

I'm not sure what the oauth official param is but I noticed on Google's OAuth API they use redirect_uri. Should this be something you can customize? Also, I noticed in the README it says to use redirect_url, and when I use that URL, that seems to work and not redirect_uri using osin. I did a search of the entire repo on osin and I don't see how redirect_url even works and not redirect_uri. Any ideas?

access type client_credentials returns refresh token

I'm playing around with osin to get a better grip on how Oauth works and how I should use it with projects. Using the example with the /token endpoint it returns a refresh_token. But as I understand this is against the specs:

4.4. Client Credentials Grant
...
4.4.3. Access Token Response

If the access token request is valid and authorized, the
authorization server issues an access token as described in
Section 5.1. A refresh token SHOULD NOT be included. If the request
failed client authentication or is invalid, the authorization server
returns an error response as described in Section 5.2.

Is there a way to disable / work around this behavior?

rfc6819: No cleartext storage of credentials

5.1.4.1.3. No Cleartext Storage of Credentials
The authorization server should not store credentials in clear text.
Typical approaches are to store hashes instead or to encrypt
credentials. If the credential lacks a reasonable entropy level
(because it is a user password), an additional salt will harden the
storage to make offline dictionary attacks more difficult.
Note: Some authentication protocols require the authorization server
to have access to the secret in the clear. Those protocols cannot be
implemented if the server only has access to hashes. Credentials
should be strongly encrypted in those cases.

OAuth 2.0 Threat Model and Security Considerations

Gaining access to the database, e.g. by using SQL Injection (OWASP's #1 attack vector), would provide an attacker with long lived credentials (refresh tokens) and short lived credentials (authorize code, access token). Having client passwords stored securely is nice and all but gives a false sense of security, because all other credentials are stored in a insecure way.

Right now, a storage could implement encryption and en-/decrypt tokens on SaveAccess / LoadAccess / etc. In an ideal world, we should not rely on encryption but rather on hashing, but that option is currently not possible in a performant way unless unsalted md5 / crc32 / shaXYZ is used. Unsalted hashing is considered bad practice for long living credentials (:= refresh tokens).

Ideally, a token would consist of two parts: {random-string-without-dots}.{signature}
Only the signature is stored. The authorization server would then first validate if random-string matches signature (e.g. by using BCrypt) and reject the token/code if the two mismatch. It would then lookup the signature in the database confirming that the token/code exists and return the appropriate data. An attacker who gained access to the database would then only have the signature which is useless without the random-string. With BCrypt it would practically be impossible to find the matching random-string in a reasonable time.

If encryption (AES) was used, an attacker who gained access to both database and app server would have access to the encryption key, rendering the security measure insecure. If hashing is used, there is no way to guess the credentials, even if an attacker has access to both systems. Only changes to the code base might disable these security measures. These however will probably be catched by a sysadmin in reasonable time.

Yes, this could be implemented by providing a custom store implementation and token generation strategy. But the store would become a validator and suddenly be more than just storage. Additionally, you can not use any of the storage implementations listed in the readme. Plus this library should enforce secure behavior rather than making insecure behavior so easy to get right.

I fell into that pitfall and it will take me significant time to refactor it and get security right. And seeing how popular this repository is amongst gophers I have reasonable doubt that some applications / companies out there are not as secure as they claim or think.

Question on Assertion support

So I was skimming through RFC6749 and saw that it doesn't really specify assertions in a detailed manner, but the example it provides is very different from the explanation of assertions in the v10 draft. I did a little more digging and found https://tools.ietf.org/html/draft-ietf-oauth-assertions-18. I was wondering what the view was on assertions support since the OAuth assertions draft is dramatically different from that specified in the OAuth2 v10 draft (which is what is currently implemented).

Thoughts?

Complete example Goto Token URL failes

As a quick glimpse of this oauth provider usage, example/complete is doing a good job, but the 'Goto Token URL' function fails, error msg:

{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."}

console log:

ERROR: Client authentication not sent

Is there anything should be adjusted?

Osin generates very similar tokens

Hi there,

I used this library for a small project a few months ago and it worked flawlessly.
However, when I came back to using it for a new project, I noticed that the tokens that are generated by osin look very similar (AccessToken & RefreshToken that is).

Here is a short program demonstrating the issue https://gist.github.com/Ligustah/bee3217f5b6c037bbf78 , which I think was introduced here: https://github.com/RangelReale/osin/pull/45

To see the difference please compare:
https://godoc.org/code.google.com/p/go-uuid/uuid#NewUUID
https://godoc.org/code.google.com/p/go-uuid/uuid#New

Now I'm not too sure as to what the implications of this are, but it think it defeats the purpose of the long lived refresh token vs. short lived access token, when it's trivial to easily guess the refresh token given a specific access token.

I suggest that you provide a default token generator that uses actually secure random tokens, which is fairly trivial using the standard library and doesn't require UUIDs at all.

Not sure if below code compiles, but I'm using a similar piece of code for another project and assuming crypto/rand is reliable it will generate fairly secure random tokens.

import (
    "crypto/rand"
    "encoding/base64"
)

func generateToken(length int) (secret string, err error) {
    var buf = make([]byte, length)
    _, err = rand.Read(buf)
    secret = base64.URLEncoding.EncodeToString(buf)

    return
}

Add support to retrieve token info based on authentication header

Currently, the way we retrieve token information is based on the query string. I have a client which sends the access_token via header already. To avoid breaking current users, we could keep both:

curl -i http://localhost:8000/me?code=ZGQyN2UyYWUtODczNS00NzAzLTllNzEtMzJlZjM0ZTliY2E1

and

curl -i -H "Authentication: Bearer ZGQyN2UyYWUtODczNS00NzAzLTllNzEtMzJlZjM0ZTliY2E1" http://localhost:8000/me

What do you think about it? If you agree I can send a pull request.
https://github.com/RangelReale/osin/blob/1bb768e23b70885ba6dc41a4e1d633aff5591e52/info.go#L20-L22

Custom client

Would you consider switching osin.Client to be an interface, much like Storage? Or to avoid BC could potentially create a osin.ClientInterface (can't think of a better name) with osin.Client as the default implementation.

We'd like to be able to offer client registration via a website for developers, as well as Id, Client, Secret we'd like some other information (like contact email, developer name, application name etc).

There's also some other things we'd like to be able to overwrite, for example the JSON marshalling (hiding the secret).

Happy to submit a pull if it's a change that'd be welcomed :)

Authorize not found

I am trying to implement your server this with: golang.org/x/oauth2 (that is client). It seams to me that everything works ok (code is generated, client_id and client secret are working ok and so on). Error I am getting is this one:

&{   0001-01-01 00:00:00 +0000 UTC map[error:invalid_grant error_description:The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.]}

that error occurs in : handleAuthorizationCodeRequest func on line 182: ret.AuthorizeData, err = w.Storage.LoadAuthorize(ret.Code)

This is my code:

var Endpoint = oauth2.Endpoint{
    AuthURL:  "http://localhost:9000/authorize",
    TokenURL: "http://localhost:9000/token",
}

ccc := &oauth2.Config{

    ClientID:     "id",
    ClientSecret: "sec",
    RedirectURL:  "http://localhost:9000",
    Scopes:[]string{"everything"},
    Endpoint: Endpoint,
}

if len(code) > 0{
    tok, err := ccc.Exchange(oauth2.NoContext, code)

    if err != nil {
        log.Println("err is", err)

        return nil
    }

    log.Println(tok)

} else {

    url := ccc.AuthCodeURL("xyz")
    log.Println(url)
    return c.Redirect(url)
}

where authorize/ route and token route are from your manual so nothing is new there.

i have tried that osincli client as well but error message is the same one.
I see your all examples uses get (that sucks do not you think?)

Osin + Mngo issue: Unable to use interface

Hi, first, I would like to thank you for this amazing project!

I'm trying to use mongodb with mgo and I'm unable to get it running due to the latest changes. Even when I try to use DefaulClient I'm getting an error:

authData := &osin.AuthorizeData{
    Client: &osin.DefaultClient{},
}
err = conn.Authorizations().Find(bson.M{"code": code}).One(authData)

Error:

ERROR: reflect.Set: value of type bson.M is not assignable to type osin.Client

One way would be convert the authorize data to a custom struct where the client is a string(object id representation) and create two other methods to convert it. Not sure if that's a great solution. Could you please help me out?
Thanks!

MAC token type

I was wondering if you have any plan to support MAC tokens?

Merging Authorization Server and Resource Server with Osin

Hi!
I'm trying to create one service with Authorization Server and Resource Server's endpoints (using revel)

I ran into one problem:

As far as I understand the code the Resource Server is supposed to use the /info endpoint to check if the token has required rights.

Is it possible to check if caller has access to a resource using Osin? (Omitting the unnecessary http call.)

Thanks!

Change to Storage interface to accept context interface

I would like to modify the storage interface to accept an interface for context information.

i.e.

// GetClient loads the client by id (client_id)
GetClient(context interface{}, id string) (Client, error)

It would also require changes to the response to accept a Context to be included in the response that could be passed into the storage calls.

// Server response
type Response struct {
    Context            interface{}

This would be a breaking change. Would this be considered for a merge?

Config for parameter names

It would be nice to be able to customize the parameter names return in the JSON output. For instance I'm building an api that uses all camel case responses, however osin always returns snake case access_token, error_description. I guess its a small point, but would be nice to be able to customize this.

Authorization Code Flow redirecting user-agent when redirect-uri is invalid

When passing an invalid redirect_uri the user-agent has been redirected with the error description as follow:

https://my-url?error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed.

Looking at the code, I see that it forces the redirection but I didn't get the point. Why is it necessary?
https://github.com/RangelReale/osin/blob/master/authorize.go#L132-L133

And the RFC says that we should not redirect the user-agent, btw..

3.1.2.4. Invalid Endpoint

If an authorization request fails validation due to a missing,
invalid, or mismatching redirection URI, the authorization server
SHOULD inform the resource owner of the error and MUST NOT
automatically redirect the user-agent to the invalid redirection URI.

Information endpoint receives access token as parameter "code"

The current information endpoint reads the access token from parameter "code". In other OAuth2 server implementation, however, they'd use "access_token" instead.

The relevant code:

I can provide a modification to (IMO) fix this, but I'd like to discuss how best to change / no change the current code first.

Is there any reason behind the decision?
Isn't "access_token" a more sensible choice?

Examples broken

http://localhost:14000/appauth/password returns

APP AUTH - PASSWORD
ERROR: invalid_request
FULL RESULT: map[error:invalid_request error_description:The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.]

newbie build questions

Hi dear osin team,
I'm just started with go and your project - can you help me with 2 questions:

  1. How to install your project?
    according 'go help gopath' structure of axample project should be different from your current, so I'm lost a bit how to make your project
  2. How to run example ?
    It's maybe same issue as with question 1, but now in './simple/simple.go' i have numerous compilation errors - changing import to 'import osin 'import osin "github.com/RangelReale/osin" ' aren't helping.
    P.S.: "I have go version go1.2.2 linux/amd64, fedora 20"
    Thand you for help, Artem

Multiple login refresh token issue

My authentication server uses password grant type to generate access tokens using OSIN. This alone works fine when multiple devices login concurrently. Issues arise, however, when one of the devices uses their refresh token to get a new access token. Because OSIN removes the old refresh token and access token whenever a refreshtoken is used, the other device (which doesn't know these have been removed) fails the next request since the accesstoken is now invalid and also fails to get a new token since the refresh token is also now invalid.

Here is the exact piece of code that causes this issue in access.go:

// remove previous access token
if ret.AccessData != nil {
    if ret.AccessData.RefreshToken != "" {
        w.Storage.RemoveRefresh(ret.AccessData.RefreshToken)
    }
    w.Storage.RemoveAccess(ret.AccessData.AccessToken)
}

I am not sure how to get around this, however. I thought about using the AccessRequest.ForceAccessData field, but I can't think of a way to reliably retrieve an existing access token when all I have is a username and password.

Any ideas on this?

Propose a breaking change for GAE Storage implementation

As mentioned in pull request #24, all storage engines of GAE requires the current *http.Request to work with. There is no way a Storage implementation can obtain such information.

There are 2 ways, I can think of, to cater the need:

  1. Change all Storage methods to accept a *http.Request parameter
  2. Change Storage.Clone() to collect *http.Request as a parameter
    This also requires the change in NewResponse() or Server.NewResponse() call

Change 1 is more intuitive but also more invasive. Users will have to change all their Storage methods. Change 2 require less changes to users' code and is much preferable.

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.