Merge pull request #233 from iegomez/feat/http-method-option
HTTP/JWT request method
This commit is contained in:
commit
d904546ac6
|
@ -892,8 +892,9 @@ The following `auth_opt_` options are supported by the `jwt` backend when remote
|
|||
| jwt_response_mode | status | N | Response type (status, json, text) |
|
||||
| jwt_params_mode | json | N | Data type (json, form) |
|
||||
| jwt_user_agent | mosquitto | N | User agent for requests |
|
||||
| jwt_http_method | POST | N | Http method used (POST, GET, PUT) |
|
||||
|
||||
URIs (like jwt_getuser_uri) are expected to be in the form `/path`. For example, if jwt_with_tls is `false`, jwt_host is `localhost`, jwt_port `3000` and jwt_getuser_uri is `/user`, mosquitto will send a POST request to `http://localhost:3000/user` to get a response to check against. How data is sent (either json encoded or as form values) and received (as a simple http status code, a json encoded response or plain text), is given by options jwt_response_mode and jwt_params_mode.
|
||||
URIs (like jwt_getuser_uri) are expected to be in the form `/path`. For example, if jwt_with_tls is `false`, jwt_host is `localhost`, jwt_port `3000` and jwt_getuser_uri is `/user`, mosquitto will send a http request to `http://localhost:3000/user` to get a response to check against. How data is sent (either json encoded or as form values) and received (as a simple http status code, a json encoded response or plain text), is given by options jwt_response_mode and jwt_params_mode.
|
||||
|
||||
If the option `jwt_superuser_uri` is not set then `superuser` checks are disabled for this mode.
|
||||
|
||||
|
@ -1144,6 +1145,7 @@ The following `auth_opt_` options are supported:
|
|||
| http_params_mode | json | N | Data type (json, form) |
|
||||
| http_timeout | 5 | N | Timeout in seconds |
|
||||
| http_user_agent | mosquitto | N | User Agent to use in requests |
|
||||
| http_method | POST | N | Http method used (POST, GET, PUT) |
|
||||
|
||||
#### Response mode
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ type HTTP struct {
|
|||
WithTLS bool
|
||||
VerifyPeer bool
|
||||
ParamsMode string
|
||||
httpMethod string
|
||||
ResponseMode string
|
||||
Timeout int
|
||||
Client *h.Client
|
||||
|
@ -45,6 +46,7 @@ func NewHTTP(authOpts map[string]string, logLevel log.Level, version string) (HT
|
|||
VerifyPeer: false,
|
||||
ResponseMode: "status",
|
||||
ParamsMode: "json",
|
||||
httpMethod: h.MethodPost,
|
||||
}
|
||||
|
||||
missingOpts := ""
|
||||
|
@ -62,6 +64,13 @@ func NewHTTP(authOpts map[string]string, logLevel log.Level, version string) (HT
|
|||
}
|
||||
}
|
||||
|
||||
if httpMethod, ok := authOpts["http_method"]; ok {
|
||||
switch httpMethod {
|
||||
case h.MethodGet, h.MethodPut:
|
||||
http.httpMethod = httpMethod
|
||||
}
|
||||
}
|
||||
|
||||
if userUri, ok := authOpts["http_getuser_uri"]; ok {
|
||||
http.UserUri = userUri
|
||||
} else {
|
||||
|
@ -210,6 +219,12 @@ func (o HTTP) httpRequest(uri, username string, dataMap map[string]interface{},
|
|||
var err error
|
||||
|
||||
if o.ParamsMode == "form" {
|
||||
if o.httpMethod != h.MethodPost && o.httpMethod != h.MethodPut {
|
||||
log.Errorf("error form param only supported for POST/PUT.")
|
||||
err = fmt.Errorf("form only supported for POST/PUT, error code: %d", 500)
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err = o.Client.PostForm(fullUri, urlValues)
|
||||
} else {
|
||||
var dataJson []byte
|
||||
|
@ -222,7 +237,7 @@ func (o HTTP) httpRequest(uri, username string, dataMap map[string]interface{},
|
|||
|
||||
contentReader := bytes.NewReader(dataJson)
|
||||
var req *h.Request
|
||||
req, err = h.NewRequest("POST", fullUri, contentReader)
|
||||
req, err = h.NewRequest(o.httpMethod, fullUri, contentReader)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("req error: %s", err)
|
||||
|
@ -236,7 +251,7 @@ func (o HTTP) httpRequest(uri, username string, dataMap map[string]interface{},
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("POST error: %s", err)
|
||||
log.Errorf("http request error: %s", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ func TestHTTPAllJsonServer(t *testing.T) {
|
|||
hb, err := NewHTTP(authOpts, log.DebugLevel, version)
|
||||
So(err, ShouldBeNil)
|
||||
So(hb.UserAgent, ShouldEqual, "mosquitto-2.0.0")
|
||||
So(hb.httpMethod, ShouldEqual, http.MethodPost)
|
||||
|
||||
Convey("Given custom user agent, it should override default one", func() {
|
||||
customAuthOpts := make(map[string]string)
|
||||
|
@ -118,6 +119,34 @@ func TestHTTPAllJsonServer(t *testing.T) {
|
|||
So(customHb.UserAgent, ShouldEqual, "custom-user-agent")
|
||||
})
|
||||
|
||||
Convey("Given http method GET, it should override the default POST one", func() {
|
||||
customAuthOpts := make(map[string]string)
|
||||
|
||||
for k, v := range authOpts {
|
||||
customAuthOpts[k] = v
|
||||
}
|
||||
|
||||
customAuthOpts["http_method"] = "GET"
|
||||
|
||||
customHb, err := NewHTTP(customAuthOpts, log.DebugLevel, version)
|
||||
So(err, ShouldBeNil)
|
||||
So(customHb.httpMethod, ShouldEqual, http.MethodGet)
|
||||
})
|
||||
|
||||
Convey("Given http method PUT, it should override the default POST one", func() {
|
||||
customAuthOpts := make(map[string]string)
|
||||
|
||||
for k, v := range authOpts {
|
||||
customAuthOpts[k] = v
|
||||
}
|
||||
|
||||
customAuthOpts["http_method"] = "PUT"
|
||||
|
||||
customHb, err := NewHTTP(customAuthOpts, log.DebugLevel, version)
|
||||
So(err, ShouldBeNil)
|
||||
So(customHb.httpMethod, ShouldEqual, http.MethodPut)
|
||||
})
|
||||
|
||||
Convey("Given correct password/username, get user should return true", func() {
|
||||
|
||||
authenticated, err := hb.GetUser(username, password, clientId)
|
||||
|
|
|
@ -27,6 +27,7 @@ type remoteJWTChecker struct {
|
|||
verifyPeer bool
|
||||
|
||||
paramsMode string
|
||||
httpMethod string
|
||||
responseMode string
|
||||
|
||||
options tokenOptions
|
||||
|
@ -45,6 +46,7 @@ func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions, versi
|
|||
verifyPeer: false,
|
||||
responseMode: "status",
|
||||
paramsMode: "json",
|
||||
httpMethod: h.MethodPost,
|
||||
options: options,
|
||||
}
|
||||
|
||||
|
@ -63,6 +65,13 @@ func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions, versi
|
|||
}
|
||||
}
|
||||
|
||||
if httpMethod, ok := authOpts["jwt_http_method"]; ok {
|
||||
switch httpMethod {
|
||||
case h.MethodGet, h.MethodPut:
|
||||
checker.httpMethod = httpMethod
|
||||
}
|
||||
}
|
||||
|
||||
if userUri, ok := authOpts["jwt_getuser_uri"]; ok {
|
||||
checker.userUri = userUri
|
||||
} else {
|
||||
|
@ -239,7 +248,7 @@ func (o *remoteJWTChecker) jwtRequest(host, uri, token string, dataMap map[strin
|
|||
}
|
||||
|
||||
contentReader := bytes.NewReader(dataJSON)
|
||||
req, err = h.NewRequest("POST", fullURI, contentReader)
|
||||
req, err = h.NewRequest(o.httpMethod, fullURI, contentReader)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("req error: %s", err)
|
||||
|
@ -248,7 +257,7 @@ func (o *remoteJWTChecker) jwtRequest(host, uri, token string, dataMap map[strin
|
|||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", o.userAgent)
|
||||
default:
|
||||
req, err = h.NewRequest("POST", fullURI, strings.NewReader(urlValues.Encode()))
|
||||
req, err = h.NewRequest(o.httpMethod, fullURI, strings.NewReader(urlValues.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Content-Length", strconv.Itoa(len(urlValues.Encode())))
|
||||
req.Header.Set("User-Agent", o.userAgent)
|
||||
|
|
Loading…
Reference in New Issue