Sono in grado di utilizzare PUT per comportarmi come GET quando utilizzo la mia API REST

1

Ho scritto una semplice API REST (semplicemente imparando) usando Go e sto chiamando usando python requests . Ho due metodi, "update_x", che aggiorna il valore della risorsa, "get_x_times_n" che ottiene il valore della risorsa. Logicamente, penserei che ho bisogno (e posso solo usare) put per "update_x" e get per "get_x_times_n". Tuttavia, posso facilmente implementare un metodo, in modo tale che possa chiamare "get_x_times_n" utilizzando put .

Ecco il mio Go code:

package main

import (
    "fmt"
    "log"
    "io"
    "io/ioutil"
    "net/http"
    "encoding/json"
    "strconv"
)

func main() {
    my_resource := MyResource{x: 0}

    http.HandleFunc("/update_x", my_resource.update_x)
    http.HandleFunc("/get_x_times_n", my_resource.get_x_times_n)
    http.HandleFunc("/get_x_times_n_wierd", my_resource.get_x_times_n_wierd)
    http.ListenAndServe("localhost:8000", nil)
}

type MyResource struct {
    x int 
}

func (mr *MyResource) update_x(w http.ResponseWriter, r *http.Request) {

    body, err := ioutil.ReadAll(io.Reader(r.Body))
    if err != nil {
        panic(err)
    }

    if err := r.Body.Close(); err != nil {
        panic(err)
    }

    var delta int 

    err = json.Unmarshal(body, &delta)

    if err != nil {
        panic(err)
    }
    mr.x += delta 
}

func (mr *MyResource) get_x_times_n(w http.ResponseWriter, r *http.Request) {

    err := r.ParseForm()
    if err != nil {
        panic(err)
    }

    log.Println(r.Form)

    n_str := r.Form["n"][0]

    n, err := strconv.Atoi(n_str)

    if err != nil {
        panic(err)
    }

    result := mr.x * n 

    fmt.Fprint(w, result)
}


func (mr *MyResource) get_x_times_n_wierd(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Body)
    body, err := ioutil.ReadAll(io.Reader(r.Body))
    if err != nil {
        panic(err)
    }

    if err := r.Body.Close(); err != nil {
        panic(err)
    }

    var n int 

    err = json.Unmarshal(body, &n)

    if err != nil {
        panic(err)
    }

    result := mr.x * n 

    fmt.Fprint(w, result)
}

Ed ecco la mia sessione Python:

In [51]: import requests

In [52]: r = requests.put("http://localhost:8000/update_x", data='5')
In [53]: r = requests.get("http://localhost:8000/get_x_times_n", params={"n": 5})

In [54]: r.content
Out[54]: '25'

In [55]: r = requests.put("http://localhost:8000/get_x_times_n_wierd", data="5")

In [56]: r.content
Out[56]: '25'

Posso capire perché questo sta accadendo, dal momento che in entrambi i metodi ho r *http.Request , posso passare qualsiasi dato che voglio. E anche in entrambi i metodi ho accesso a w http.ResponseWriter , posso scrivere tutto ciò che voglio.

La mia domanda è: cosa sto sbagliando? Sto solo abusando di requests quando utilizzo l'API? Ho impostato la mia API completamente sbagliato? (Se l'API è stata impostata correttamente, qualcosa di simile non sarebbe consentito?). O entrambi? O forse qualcos'altro?

    
posta Akavall 24.09.2015 - 05:35
fonte

1 risposta

2

Nessun elemento incorporato nel server comprenderà che una richiesta avrebbe dovuto essere una richiesta PUT. (Come potrebbe?) Sta a te gestirlo. Il comportamento predefinito per il server http go è semplicemente quello di ignorare il metodo. (Alcuni altri sistemi hanno altre impostazioni predefinite, ad esempio solo il supporto GET per impostazione predefinita). Se desideri che una particolare richiesta funzioni solo se utilizzata con un determinato metodo http, devi applicarla. Qualcosa come:

if r.Method != "PUT" {
   sendRejection(w);
}

La mia raccomandazione è di applicare sempre il metodo corretto.

    
risposta data 24.09.2015 - 06:46
fonte

Leggi altre domande sui tag