Created
March 19, 2023 09:09
-
-
Save visopsys/bc6bf95df74e38382e27de6a08d8e5ff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io/ioutil" | |
| "net/http" | |
| "os" | |
| "time" | |
| ) | |
| func postHelloMessage() { | |
| body := []byte(`{ | |
| "first_name": "John" | |
| }`) | |
| req, err := http.NewRequest(http.MethodPost, "http://localhost:3333/PostHelloMessage", bytes.NewBuffer(body)) | |
| if err != nil { | |
| fmt.Printf("client: could not create request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| client := http.Client{ | |
| Timeout: 30 * time.Second, | |
| } | |
| res, err := client.Do(req) | |
| if err != nil { | |
| fmt.Printf("client: error making http request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| defer res.Body.Close() | |
| bz, err := ioutil.ReadAll(res.Body) | |
| fmt.Println("Response = ", string(bz)) | |
| } | |
| func Redirect() { | |
| req, err := http.NewRequest(http.MethodPost, "http://localhost:3333/Redirect", nil) | |
| if err != nil { | |
| fmt.Printf("client: could not create request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| client := http.Client{ | |
| Timeout: 30 * time.Second, | |
| } | |
| res, err := client.Do(req) | |
| if err != nil { | |
| fmt.Printf("client: error making http request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| defer res.Body.Close() | |
| bz, err := ioutil.ReadAll(res.Body) | |
| fmt.Println("Response = ", string(bz)) | |
| } | |
| func GetMessage() { | |
| req, err := http.NewRequest(http.MethodPost, "http://localhost:3333/GetMesasge?name=aaaa,bbbb", nil) | |
| if err != nil { | |
| fmt.Printf("client: could not create request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| client := http.Client{ | |
| Timeout: 30 * time.Second, | |
| } | |
| res, err := client.Do(req) | |
| if err != nil { | |
| fmt.Printf("client: error making http request: %s\n", err) | |
| os.Exit(1) | |
| } | |
| defer res.Body.Close() | |
| bz, err := ioutil.ReadAll(res.Body) | |
| fmt.Println("Response = ", string(bz)) | |
| } | |
| func main() { | |
| // postHelloMessage() | |
| // Redirect() | |
| GetMessage() | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "encoding/json" | |
| "fmt" | |
| "io/ioutil" | |
| "net/http" | |
| "net/url" | |
| "reflect" | |
| ) | |
| type T struct{} | |
| type PostRequest struct { | |
| Firstname string `json:"first_name"` | |
| } | |
| type PostResponse struct { | |
| HelloMessage string `json:"hello_message"` | |
| } | |
| type GetResponse struct { | |
| Message string `json:"message"` | |
| } | |
| type Api struct { | |
| } | |
| func (a *Api) PostHelloMessage(extras map[string]any, e PostRequest) (PostResponse, error) { | |
| return PostResponse{ | |
| HelloMessage: "hello " + e.Firstname, | |
| }, nil | |
| } | |
| func (a *Api) Redirect(extras map[string]any, params map[string][]string) { | |
| var writer http.ResponseWriter | |
| var request *http.Request | |
| writer = extras["writer"].(http.ResponseWriter) | |
| request = extras["request"].(*http.Request) | |
| http.Redirect(writer, request, "https://example.com", http.StatusSeeOther) | |
| } | |
| func (a *Api) GetMesasge(extras map[string]any, params map[string][]string) (GetResponse, error) { | |
| names := params["name"] | |
| var name string | |
| if len(names) > 0 { | |
| name = names[0] | |
| } | |
| return GetResponse{ | |
| Message: "Some message from server to " + name, | |
| }, nil | |
| } | |
| func InvokePostFuncCall(fn interface{}, extras map[string]any, jsonData []byte) []reflect.Value { | |
| vfn := reflect.ValueOf(fn) | |
| // Get first arg of the function | |
| secondArg := reflect.TypeOf(fn).In(1) | |
| // Get the PtrTo to the first function parameter | |
| structPtr := reflect.New(secondArg) | |
| // Convert to Interface | |
| // Note that I can't assert this to .(myStruct) type | |
| instance := structPtr.Interface() | |
| // Unmarshal the JSON | |
| err := json.Unmarshal(jsonData, instance) | |
| if err != nil { | |
| // TODO: return error here. | |
| } | |
| // Call the function | |
| return vfn.Call([]reflect.Value{reflect.ValueOf(extras), structPtr.Elem()}) | |
| } | |
| func InvokeGet(fn interface{}, extras map[string]any, params map[string][]string) []reflect.Value { | |
| vfn := reflect.ValueOf(fn) | |
| return vfn.Call([]reflect.Value{reflect.ValueOf(extras), reflect.ValueOf(params)}) | |
| } | |
| func TestInvokeFunc() { | |
| // Unmarshal to reflected struct | |
| api := new(Api) | |
| values := InvokePostFuncCall(api.PostHelloMessage, map[string]any{}, | |
| []byte("{\"first_name\": \"beeeeeder\"}")) | |
| fmt.Println("Values[0] = ", values[0]) | |
| } | |
| func testServer() { | |
| type handlerMethod struct { | |
| Method string | |
| Handler any | |
| OverrideResponse bool // Set this to true when the handler wants to handle the response write. | |
| } | |
| api := new(Api) | |
| m := map[string]handlerMethod{ | |
| "/PostHelloMessage": { | |
| Method: "POST", | |
| Handler: api.PostHelloMessage, | |
| }, | |
| "/Redirect": { | |
| Method: "GET", | |
| Handler: api.Redirect, | |
| OverrideResponse: true, | |
| }, | |
| "/GetMesasge": { | |
| Method: "GET", | |
| Handler: api.GetMesasge, | |
| }, | |
| } | |
| middleware := func(writer http.ResponseWriter, request *http.Request) { | |
| methodHandler, ok := m[request.URL.Path] | |
| if !ok { | |
| writer.WriteHeader(http.StatusNotFound) | |
| return | |
| } | |
| extras := map[string]any{ | |
| "request": request, | |
| "writer": writer, | |
| } | |
| var body []byte | |
| var values []reflect.Value | |
| switch methodHandler.Method { | |
| case "POST": | |
| // Read the Json in the body | |
| var err error | |
| body, err = ioutil.ReadAll(request.Body) | |
| if err != nil { | |
| writer.WriteHeader(http.StatusBadRequest) | |
| return | |
| } | |
| values = InvokePostFuncCall(methodHandler.Handler, extras, body) | |
| case "GET": | |
| // Parse the query params | |
| parsedValues, err := url.ParseQuery(request.URL.RawQuery) | |
| if err != nil { | |
| writer.WriteHeader(http.StatusBadRequest) | |
| return | |
| } | |
| values = InvokeGet(methodHandler.Handler, extras, parsedValues) | |
| } | |
| if !methodHandler.OverrideResponse { | |
| switch len(values) { | |
| case 2: | |
| if values[1].IsNil() { | |
| bz, err := json.Marshal(values[0].Interface()) | |
| if err != nil { | |
| writer.WriteHeader(http.StatusInternalServerError) | |
| return | |
| } | |
| writer.Write(bz) | |
| } else { | |
| // Handle error here. | |
| } | |
| } | |
| } else { | |
| // Do nothing since the function already handled the response. | |
| } | |
| } | |
| mux := http.NewServeMux() | |
| mux.Handle("/", http.HandlerFunc(middleware)) | |
| fmt.Println("Starting server") | |
| http.ListenAndServe(":3333", mux) | |
| } | |
| func main() { | |
| testServer() | |
| // Unmarshal() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment