| // Copyright 2017 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package main |
| |
| import ( |
| "fmt" |
| |
| surface "github.com/googleapis/gnostic/surface" |
| ) |
| |
| func (renderer *Renderer) RenderServer() ([]byte, error) { |
| f := NewLineWriter() |
| f.WriteLine("// GENERATED FILE: DO NOT EDIT!") |
| f.WriteLine(``) |
| f.WriteLine("package " + renderer.Package) |
| f.WriteLine(``) |
| imports := []string{ |
| "github.com/gorilla/mux", |
| "net/http", |
| } |
| f.WriteLine(``) |
| f.WriteLine(`import (`) |
| for _, imp := range imports { |
| f.WriteLine(`"` + imp + `"`) |
| } |
| f.WriteLine(`)`) |
| |
| f.WriteLine(`func intValue(s string) (v int64) {`) |
| f.WriteLine(` v, _ = strconv.ParseInt(s, 10, 64)`) |
| f.WriteLine(` return v`) |
| f.WriteLine(`}`) |
| f.WriteLine(``) |
| f.WriteLine(`// This package-global variable holds the user-written Provider for API services.`) |
| f.WriteLine(`// See the Provider interface for details.`) |
| f.WriteLine(`var provider Provider`) |
| f.WriteLine(``) |
| f.WriteLine(`// These handlers serve API methods.`) |
| f.WriteLine(``) |
| |
| for _, method := range renderer.Model.Methods { |
| parametersType := renderer.Model.TypeWithTypeName(method.ParametersTypeName) |
| responsesType := renderer.Model.TypeWithTypeName(method.ResponsesTypeName) |
| |
| f.WriteLine(`// Handler`) |
| f.WriteLine(commentForText(method.Description)) |
| f.WriteLine(`func ` + method.HandlerName + `(w http.ResponseWriter, r *http.Request) {`) |
| f.WriteLine(` var err error`) |
| if parametersType != nil { |
| f.WriteLine(`// instantiate the parameters structure`) |
| f.WriteLine(`parameters := &` + parametersType.Name + `{}`) |
| if method.Method == "POST" { |
| f.WriteLine(`// deserialize request from post data`) |
| f.WriteLine(`decoder := json.NewDecoder(r.Body)`) |
| f.WriteLine(`err = decoder.Decode(¶meters.` + |
| parametersType.FieldWithPosition(surface.Position_BODY).FieldName + `)`) |
| f.WriteLine(`if err != nil {`) |
| f.WriteLine(` w.WriteHeader(http.StatusBadRequest)`) |
| f.WriteLine(` w.Write([]byte(err.Error() + "\n"))`) |
| f.WriteLine(` return`) |
| f.WriteLine(`}`) |
| } |
| f.WriteLine(`// get request fields in path and query parameters`) |
| if parametersType.HasFieldWithPosition(surface.Position_PATH) { |
| f.WriteLine(`vars := mux.Vars(r)`) |
| } |
| if parametersType.HasFieldWithPosition(surface.Position_FORMDATA) { |
| f.WriteLine(`r.ParseForm()`) |
| } |
| for _, field := range parametersType.Fields { |
| if field.Position == surface.Position_PATH { |
| if field.Type == "string" { |
| f.WriteLine(fmt.Sprintf("// %+v", field)) |
| f.WriteLine(`if value, ok := vars["` + field.Name + `"]; ok {`) |
| f.WriteLine(` parameters.` + field.FieldName + ` = value`) |
| f.WriteLine(`}`) |
| } else { |
| f.WriteLine(`if value, ok := vars["` + field.Name + `"]; ok {`) |
| f.WriteLine(` parameters.` + field.FieldName + ` = intValue(value)`) |
| f.WriteLine(`}`) |
| } |
| } else if field.Position == surface.Position_FORMDATA { |
| f.WriteLine(`if len(r.Form["` + field.Name + `"]) > 0 {`) |
| f.WriteLine(` parameters.` + field.FieldName + ` = intValue(r.Form["` + field.Name + `"][0])`) |
| f.WriteLine(`}`) |
| } |
| } |
| } |
| if responsesType != nil { |
| f.WriteLine(`// instantiate the responses structure`) |
| f.WriteLine(`responses := &` + method.ResponsesTypeName + `{}`) |
| } |
| f.WriteLine(`// call the service provider`) |
| callLine := `err = provider.` + method.ProcessorName |
| if parametersType != nil { |
| if responsesType != nil { |
| callLine += `(parameters, responses)` |
| } else { |
| callLine += `(parameters)` |
| } |
| } else { |
| if responsesType != nil { |
| callLine += `(responses)` |
| } else { |
| callLine += `()` |
| } |
| } |
| f.WriteLine(callLine) |
| f.WriteLine(`if err == nil {`) |
| if responsesType != nil { |
| if responsesType.HasFieldWithName("OK") { |
| f.WriteLine(`if responses.OK != nil {`) |
| f.WriteLine(` // write the normal response`) |
| f.WriteLine(` encoder := json.NewEncoder(w)`) |
| f.WriteLine(` encoder.Encode(responses.OK)`) |
| f.WriteLine(` return`) |
| f.WriteLine(`}`) |
| } |
| if responsesType.HasFieldWithName("Default") { |
| f.WriteLine(`if responses.Default != nil {`) |
| f.WriteLine(` // write the error response`) |
| if responsesType.FieldWithName("Default").ServiceType(renderer.Model).FieldWithName("Code") != nil { |
| f.WriteLine(` w.WriteHeader(int(responses.Default.Code))`) |
| } |
| f.WriteLine(` encoder := json.NewEncoder(w)`) |
| f.WriteLine(` encoder.Encode(responses.Default)`) |
| f.WriteLine(` return`) |
| f.WriteLine(`}`) |
| } |
| } |
| f.WriteLine(`} else {`) |
| f.WriteLine(` w.WriteHeader(http.StatusInternalServerError)`) |
| f.WriteLine(` w.Write([]byte(err.Error() + "\n"))`) |
| f.WriteLine(` return`) |
| f.WriteLine(`}`) |
| f.WriteLine(`}`) |
| f.WriteLine(``) |
| } |
| f.WriteLine(`// Initialize the API service.`) |
| f.WriteLine(`func Initialize(p Provider) {`) |
| f.WriteLine(` provider = p`) |
| f.WriteLine(` var router = mux.NewRouter()`) |
| for _, method := range renderer.Model.Methods { |
| f.WriteLine(`router.HandleFunc("` + method.Path + `", ` + method.HandlerName + `).Methods("` + method.Method + `")`) |
| } |
| f.WriteLine(` http.Handle("/", router)`) |
| f.WriteLine(`}`) |
| f.WriteLine(``) |
| f.WriteLine(`// Provide the API service over HTTP.`) |
| f.WriteLine(`func ServeHTTP(address string) error {`) |
| f.WriteLine(` if provider == nil {`) |
| f.WriteLine(` return errors.New("Use ` + renderer.Package + `.Initialize() to set a service provider.")`) |
| f.WriteLine(` }`) |
| f.WriteLine(` return http.ListenAndServe(address, nil)`) |
| f.WriteLine(`}`) |
| return f.Bytes(), nil |
| } |