2019-06-03 20:44:43 +03:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"mime"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
|
2019-06-07 15:53:42 +03:00
|
|
|
api "github.com/micro/go-micro/api/proto"
|
2019-06-21 17:13:54 +03:00
|
|
|
"github.com/micro/go-micro/client/selector"
|
2019-06-21 19:20:41 +03:00
|
|
|
"github.com/micro/go-micro/registry"
|
2019-06-03 20:44:43 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func requestToProto(r *http.Request) (*api.Request, error) {
|
|
|
|
if err := r.ParseForm(); err != nil {
|
|
|
|
return nil, fmt.Errorf("Error parsing form: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
req := &api.Request{
|
|
|
|
Path: r.URL.Path,
|
|
|
|
Method: r.Method,
|
|
|
|
Header: make(map[string]*api.Pair),
|
|
|
|
Get: make(map[string]*api.Pair),
|
|
|
|
Post: make(map[string]*api.Pair),
|
|
|
|
Url: r.URL.String(),
|
|
|
|
}
|
|
|
|
|
|
|
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
|
|
|
if err != nil {
|
|
|
|
ct = "application/x-www-form-urlencoded"
|
|
|
|
r.Header.Set("Content-Type", ct)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ct {
|
|
|
|
case "application/x-www-form-urlencoded":
|
|
|
|
// expect form vals
|
|
|
|
default:
|
|
|
|
data, _ := ioutil.ReadAll(r.Body)
|
|
|
|
req.Body = string(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set X-Forwarded-For if it does not exist
|
|
|
|
if ip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
|
|
|
|
if prior, ok := r.Header["X-Forwarded-For"]; ok {
|
|
|
|
ip = strings.Join(prior, ", ") + ", " + ip
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the header
|
|
|
|
req.Header["X-Forwarded-For"] = &api.Pair{
|
|
|
|
Key: "X-Forwarded-For",
|
|
|
|
Values: []string{ip},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Host is stripped from net/http Headers so let's add it
|
|
|
|
req.Header["Host"] = &api.Pair{
|
|
|
|
Key: "Host",
|
|
|
|
Values: []string{r.Host},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get data
|
|
|
|
for key, vals := range r.URL.Query() {
|
|
|
|
header, ok := req.Get[key]
|
|
|
|
if !ok {
|
|
|
|
header = &api.Pair{
|
|
|
|
Key: key,
|
|
|
|
}
|
|
|
|
req.Get[key] = header
|
|
|
|
}
|
|
|
|
header.Values = vals
|
|
|
|
}
|
|
|
|
|
|
|
|
// Post data
|
|
|
|
for key, vals := range r.PostForm {
|
|
|
|
header, ok := req.Post[key]
|
|
|
|
if !ok {
|
|
|
|
header = &api.Pair{
|
|
|
|
Key: key,
|
|
|
|
}
|
|
|
|
req.Post[key] = header
|
|
|
|
}
|
|
|
|
header.Values = vals
|
|
|
|
}
|
|
|
|
|
|
|
|
for key, vals := range r.Header {
|
|
|
|
header, ok := req.Header[key]
|
|
|
|
if !ok {
|
|
|
|
header = &api.Pair{
|
|
|
|
Key: key,
|
|
|
|
}
|
|
|
|
req.Header[key] = header
|
|
|
|
}
|
|
|
|
header.Values = vals
|
|
|
|
}
|
|
|
|
|
|
|
|
return req, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// strategy is a hack for selection
|
|
|
|
func strategy(services []*registry.Service) selector.Strategy {
|
|
|
|
return func(_ []*registry.Service) selector.Next {
|
|
|
|
// ignore input to this function, use services above
|
|
|
|
return selector.Random(services)
|
|
|
|
}
|
|
|
|
}
|