package http import ( "fmt" "net/http" "reflect" "strings" ) type HTTPAdapter struct { } // ServeHTTP func (a *HTTPAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { WriteError(w, 405, "rpc: POST method required, received "+r.Method) return } contentType := r.Header.Get("Content-Type") idx := strings.Index(contentType, ";") if idx != -1 { contentType = contentType[:idx] } var codec Codec if contentType == "" && len(s.codecs) == 1 { // If Content-Type is not set and only one codec has been registered, // then default to that codec. for _, c := range s.codecs { codec = c } } else if codec = s.codecs[strings.ToLower(contentType)]; codec == nil { WriteError(w, 415, "rpc: unrecognized Content-Type: "+contentType) return } // Create a new codec request. codecReq := codec.NewRequest(r) // Get service method to be called. method, errMethod := codecReq.Method() if errMethod != nil { codecReq.WriteError(w, 400, errMethod) return } serviceSpec, methodSpec, errGet := s.services.get(method) if errGet != nil { codecReq.WriteError(w, 400, errGet) return } // Decode the args. args := reflect.New(methodSpec.argsType) if errRead := codecReq.ReadRequest(args.Interface()); errRead != nil { codecReq.WriteError(w, 400, errRead) return } // Call the service method. reply := reflect.New(methodSpec.replyType) errValue := methodSpec.method.Func.Call([]reflect.Value{ serviceSpec.rcvr, reflect.ValueOf(r), args, reply, }) // Cast the result to error if needed. var errResult error errInter := errValue[0].Interface() if errInter != nil { errResult = errInter.(error) } // Prevents Internet Explorer from MIME-sniffing a response away // from the declared content-type w.Header().Set("x-content-type-options", "nosniff") // Encode the response. if errResult == nil { codecReq.WriteResponse(w, reply.Interface()) } else { codecReq.WriteError(w, 400, errResult) } } func WriteError(w http.ResponseWriter, status int, msg string) { w.WriteHeader(status) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprint(w, msg) }