detect response content-type
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
		
							
								
								
									
										39
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								http.go
									
									
									
									
									
								
							| @@ -21,7 +21,6 @@ import ( | ||||
| 	"github.com/unistack-org/micro/v3/errors" | ||||
| 	"github.com/unistack-org/micro/v3/metadata" | ||||
| 	"github.com/unistack-org/micro/v3/router" | ||||
| 	rutil "github.com/unistack-org/micro/v3/util/reflect" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -102,21 +101,9 @@ func newRequest(addr string, req client.Request, ct string, cf codec.Codec, msg | ||||
| 		return nil, errors.BadRequest("go.micro.client", err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	var b []byte | ||||
|  | ||||
| 	if nmsg != nil { | ||||
| 		if ct == "application/x-www-form-urlencoded" { | ||||
| 			data, err := rutil.StructURLValues(nmsg, "", tags) | ||||
| 			if err != nil { | ||||
| 				return nil, errors.BadRequest("go.micro.client", err.Error()) | ||||
| 			} | ||||
| 			b = []byte(data.Encode()) | ||||
| 		} else { | ||||
| 			b, err = cf.Marshal(nmsg) | ||||
| 			if err != nil { | ||||
| 				return nil, errors.BadRequest("go.micro.client", err.Error()) | ||||
| 			} | ||||
| 		} | ||||
| 	b, err := cf.Marshal(nmsg) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.BadRequest("go.micro.client", err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	if len(b) > 0 { | ||||
| @@ -145,20 +132,10 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request, | ||||
| 	// set the content type for the request | ||||
| 	header.Set("Content-Type", ct) | ||||
|  | ||||
| 	var cf codec.Codec | ||||
| 	var err error | ||||
| 	// get codec | ||||
| 	switch ct { | ||||
| 	case "application/x-www-form-urlencoded": | ||||
| 		cf, err = h.newCodec(DefaultContentType) | ||||
| 	default: | ||||
| 		cf, err = h.newCodec(ct) | ||||
| 	} | ||||
|  | ||||
| 	cf, err := h.newCodec(ct) | ||||
| 	if err != nil { | ||||
| 		return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	hreq, err := newRequest(addr, req, ct, cf, req.Body(), opts) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -184,7 +161,13 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request, | ||||
|  | ||||
| 	defer hrsp.Body.Close() | ||||
|  | ||||
| 	return parseRsp(ctx, hrsp, cf, rsp, opts) | ||||
| 	if ct == "application/x-www-form-urlencoded" { | ||||
| 		cf, err = h.newCodec(DefaultContentType) | ||||
| 		if err != nil { | ||||
| 			return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 	return h.parseRsp(ctx, hrsp, rsp, opts) | ||||
| } | ||||
|  | ||||
| func (h *httpClient) stream(ctx context.Context, addr string, req client.Request, opts client.CallOptions) (client.Stream, error) { | ||||
|   | ||||
							
								
								
									
										39
									
								
								stream.go
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								stream.go
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import ( | ||||
| 	"bufio" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
| @@ -89,7 +90,7 @@ func (h *httpStream) Recv(msg interface{}) error { | ||||
| 	} | ||||
| 	defer hrsp.Body.Close() | ||||
|  | ||||
| 	return parseRsp(h.context, hrsp, h.cf, msg, h.opts) | ||||
| 	return h.parseRsp(h.context, hrsp, h.cf, msg, h.opts) | ||||
| } | ||||
|  | ||||
| func (h *httpStream) Error() error { | ||||
| @@ -107,3 +108,39 @@ func (h *httpStream) Close() error { | ||||
| 		return h.conn.Close() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *httpStream) parseRsp(ctx context.Context, hrsp *http.Response, cf codec.Codec, rsp interface{}, opts client.CallOptions) error { | ||||
| 	var err error | ||||
|  | ||||
| 	// fast path return | ||||
| 	if hrsp.StatusCode == http.StatusNoContent { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if hrsp.StatusCode < 400 { | ||||
| 		if err = cf.ReadBody(hrsp.Body, rsp); err != nil { | ||||
| 			return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	errmap, ok := opts.Context.Value(errorMapKey{}).(map[string]interface{}) | ||||
| 	if ok && errmap != nil { | ||||
| 		if err, ok = errmap[fmt.Sprintf("%d", hrsp.StatusCode)].(error); !ok { | ||||
| 			err, ok = errmap["default"].(error) | ||||
| 		} | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		buf, err := io.ReadAll(hrsp.Body) | ||||
| 		if err != nil { | ||||
| 			errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 		} | ||||
| 		return errors.New("go.micro.client", string(buf), int32(hrsp.StatusCode)) | ||||
| 	} | ||||
|  | ||||
| 	if cerr := cf.ReadBody(hrsp.Body, err); cerr != nil { | ||||
| 		err = errors.InternalServerError("go.micro.client", cerr.Error()) | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|   | ||||
							
								
								
									
										53
									
								
								util.go
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								util.go
									
									
									
									
									
								
							| @@ -3,14 +3,13 @@ package http | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/unistack-org/micro/v3/client" | ||||
| 	"github.com/unistack-org/micro/v3/codec" | ||||
| 	"github.com/unistack-org/micro/v3/errors" | ||||
| 	rutil "github.com/unistack-org/micro/v3/util/reflect" | ||||
| 	util "github.com/unistack-org/micro/v3/util/router" | ||||
| @@ -159,48 +158,46 @@ func newTemplate(path string) (util.Template, error) { | ||||
| 	return tpl, nil | ||||
| } | ||||
|  | ||||
| func parseRsp(ctx context.Context, hrsp *http.Response, cf codec.Codec, rsp interface{}, opts client.CallOptions) error { | ||||
| func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp interface{}, opts client.CallOptions) error { | ||||
| 	// fast path return | ||||
| 	if hrsp.StatusCode == http.StatusNoContent { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	b, err := ioutil.ReadAll(hrsp.Body) | ||||
| 	ct := DefaultContentType | ||||
|  | ||||
| 	if htype := hrsp.Header.Get("Content-Type"); htype != "" { | ||||
| 		ct = htype | ||||
| 	} | ||||
|  | ||||
| 	cf, err := h.newCodec(ct) | ||||
| 	if err != nil { | ||||
| 		return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	if hrsp.StatusCode < 400 { | ||||
| 		// unmarshal only if body not nil | ||||
| 		if len(b) > 0 { | ||||
| 			// unmarshal | ||||
| 			if err := cf.Unmarshal(b, rsp); err != nil { | ||||
| 				return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 			} | ||||
| 		if err := cf.ReadBody(hrsp.Body, rsp); err != nil { | ||||
| 			return errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	errmap, ok := opts.Context.Value(errorMapKey{}).(map[string]interface{}) | ||||
| 	if !ok || errmap == nil { | ||||
| 		// user not provide map of errors | ||||
| 		// id: req.Service() ?? | ||||
| 		return errors.New("go.micro.client", string(b), int32(hrsp.StatusCode)) | ||||
| 	} | ||||
|  | ||||
| 	if err, ok = errmap[fmt.Sprintf("%d", hrsp.StatusCode)].(error); !ok { | ||||
| 		err, ok = errmap["default"].(error) | ||||
| 	} | ||||
| 	if !ok { | ||||
| 		return errors.New("go.micro.client", string(b), int32(hrsp.StatusCode)) | ||||
| 	} | ||||
|  | ||||
| 	if len(b) > 0 { | ||||
| 		if cerr := cf.Unmarshal(b, err); cerr != nil { | ||||
| 			err = errors.InternalServerError("go.micro.client", cerr.Error()) | ||||
| 	if ok && errmap != nil { | ||||
| 		if err, ok = errmap[fmt.Sprintf("%d", hrsp.StatusCode)].(error); !ok { | ||||
| 			err, ok = errmap["default"].(error) | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = errors.New("go.micro.client", string(b), int32(hrsp.StatusCode)) | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		buf, err := io.ReadAll(hrsp.Body) | ||||
| 		if err != nil { | ||||
| 			errors.InternalServerError("go.micro.client", err.Error()) | ||||
| 		} | ||||
| 		return errors.New("go.micro.client", string(buf), int32(hrsp.StatusCode)) | ||||
| 	} | ||||
|  | ||||
| 	if cerr := cf.ReadBody(hrsp.Body, err); cerr != nil { | ||||
| 		err = errors.InternalServerError("go.micro.client", cerr.Error()) | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
|   | ||||
		Reference in New Issue
	
	Block a user