Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Incorporar datos a través de HTTP POST

8/19
Recursos

Aportes 39

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

El problema con CMD de Windows está en que no soporta comillas simples, por lo tanto, debemos sustituir su uso por comillas dobles.
Para incluir los datos en json tenemos dos opciones:

  • Podemos usar el caracter de escape backslash ( \ ) antes de cada comilla dentro de los datos JSON:
curl -X "POST" http://localhost:8000/books -d "{ \"titulo\":\"Nuevo Libro\",\"id_autor\": 1,\"id_genero\": 2}"
  • También podemos mover los datos json a un archivo de tipo .txt y cambiar el cURL para que importe los datos JSON a través de la sintaxis @filename:
{
    "Titulo": "Libro Nuevo",
    "id_autor": 1,
    "id_genero": 2
}

Recuerda cambiar tu directorio a donde esta contenido el archivo json.txt (con el comando cd ) antes de realizar esta acción.

curl -X "POST" http://localhost:8000/books -d @json.txt

Para los que usan Windows, pueden usar el la consola de Ubuntu TLS para windows, que esta disponible en la store, asi se facilitan 10 años la vida y no tienen que hacer inventos raros para que funcione.

pd: pasense a linux, el mundo de programador es mas bonito desde este lado jaja

Apuntes:
Para el caso de POST, debemos validar dentro de la sentencia switch en el caso de que el verbo en la petición sea POST. Debemos asumir que los datos enviados, vengan en formato JSON, tipo de datos que definiríamos en primera instancia al crear nuestro web service.
Al momento de hacer la consulta mediante CURL, usamos a diferencia de GET, el modificador X luego del curl, seguido de esto, especificamos con ‘POST’, seguido escribimos la URL, el puerto y el identificador al que queremos agregar el elemento (en este caso books). Finalmente escribimos el modificador -d y escribimos la cadena JSON con los datos que vamos a almacenar.
IMPORTANTE
Para los que no les funcionó con el CMD de Windows, prueben de esta manera:
curl -H "Content-Type: application/json" -X POST -d "{ \"titulo\":\"Nuevo Libro\",\"id_autor\": 1,\"genero\": 2}" http://localhost:8000/books

Lo que va de la clase:

<?php
// CLASE 06 - Exponer datos a traves de HTTP GET
// definimos los recursos disponibles 

$allowedResourceTypes = [
    'books',
    'authors',
    'genres'
];

$resourceType = $_GET['resource_type'];

if( !in_array($resourceType, $allowedResourceTypes)){
    die;
}

// Defino los recursos
$books = [
    1 => [
        'titulo' => 'Lo que el viento se llevo',
        'id_autor' => 2,
        'id_genero' => 2,
    ],
    2 => [
        'titulo' => 'La Iliada',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
    3 => [
        'titulo' => 'La Odisea',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
];

// Se indica al cliente que lo que recibirá es un json
header('Content-Type: application/json');
// Levantamos el id del recurso buscado
$resourceId = array_key_exists('resource_id', $_GET) ? $_GET['resource_id']:'';

// Generamos la respuesta asumiendo que el pedido es correcto y devilvemos en formafo json
switch( strtoupper($_SERVER['REQUEST_METHOD']) ) {
    case 'GET':
        // en caso de que no pidan ningun recurso
         if ( empty( $resourceId ) ){
            echo json_encode( $books );
         }else{
             // si llegan a pedir un recurso en especifico
            if( array_key_exists( $resourceId, $books) ){
                echo json_encode( $books[ $resourceId ] );
            }
        }
        break;
    case 'POST':
        $json = file_get_contents('php://input');
        $books[] = json_decode($json, true);
        // echo array_keys( $books )[count($books) -1];
        echo json_encode($books);
        break;
    case 'PUT':
        break;
    case 'DELETE':
        break;
}



// Inicio el servidor en la terminal 1, aqui le asignamos el puerto 8000
// php -S localhost:8000 server.php

// Terminal 2 ejecutar 
// curl http://localhost:8000 -v
// curl http://localhost:8000/\?resource_type\=books
// curl http://localhost:8000/\?resource_type\=books | jq
// ver la comunicacion a través de los encabezados:
// $ curl http://localhost:8000/\?resource_type\=books -v > /dev/null
// consulta
//$curl "http://localhost:8000?resource_type=books&resource_id=1"
//curl -X 'POST' http://localhost:8000/books -d '{"titulo":"Nuevo Libro","id_autor":1,"id_genero":2}'
?>

Para enviar un Json por CMD de Windows, sustituimos lo que debe llegar con comillas dobles, con doble comillas dobles:

curl -X “POST” http://localhost:8000/books -d “{”“titulo”":"“Nuevo Libro”","“id_autor”":1,"“id_genero”":2}"

Mac:

curl -X 'POST' http://localhost:8000/books -d '{"titulo":"Nuevo Libro","id_autor":1,"id_genero":2}' | jq

Actualización de mi código en javascript:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

// Middlewares para recibir JSON a traves del API en express
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// Parametros permitidos para "resource_type"
const allowedResources = [
  'books',
  'authors',
  'genres'
];

// Array de objetos que contienen los libros
const books = [
  { title: 'Lo que el viento se llevo', id_author: 2, id_genre: 2 },
  { title: 'La Iliada', id_author: 1, id_genre: 1 },
  { title: 'La odisea', id_author: 1, id_genre: 1 }
];

app.get('/', (req, res) => {
  // Obtiene "resource_type" de los parámetros del URL
  const resourceType = req.query.resource_type;

  // Verifica si existe este parámetro en nuestro arreglo de permitidos
  if(allowedResources.indexOf(resourceType) === -1) {
    // Devuelve error si no se encuentra
    return res.json({ status: 'Failed', error: 'missing or invalid param: resource_type' });    
  }
  // Si sale todo bien, devuelve un ok junto a los libros
  res.json({ status: 'ok', books });
});

app.post('/books', (req, res) => {
  // Verifica si se envian datos por formulario
  if(req.body) {
    // Verifica si falta "title", "id_author" o "id_genre"
    if(!req.body.title || !req.body.id_author || !req.body.id_genre) {
      // Devuelve error si falta alguno
      return res.json({ status: 'failed', error: 'missing or invalid: data' });
    }

    // Inserta un nuevo objeto al array, y devuelve el id insertado 
    // (característica javascript)
    const insertCount = books.push({
      title: req.body.title,
      id_author: req.body.id_author,
      id_genre: req.body.id_genre
    })

    // Devuelve ok y el id insertado si todo salió bien
    res.json({ status: 'ok', insert_id: insertCount - 1, books })
  } else {
    // Devuelve un error si no se envian datos por formulario
    return res.json({ status: 'Failed', error: 'error no data' });
  }
})

// Iniciador del servidor, en el puerto 5000
app.listen(5000, () => {
  console.log('server on port 5000');
});

Empezar servidor:

node index.js

Consultar los libros:

curl localhost:5000?resource_type=books

Insertar un libro:

curl --header "Content-Type: application/json" -X 'POST' localhost:5000/books -d '{"title": "Nuevo libro", "id_author": 1, "id_genre": 2 }'

O si usan POSTMAN, insertarlos con “x-www-form-urlencoded”

Para que me funcionara tuve que reemplazar
$books[] = json_decode($json, true);
por
array_push($books, json_decode($json, true));
😛

Mi primer post con php :v

Si en Windows no les funciono los aportes anteriores, aqui dejo el mio que me funciono correctamente desde una terminal de Powershell…

$datos = "{\"titulo\": \"El nuevo libro\",\"id_autor\":\"1\",\"id_genero\":\"2\"}"	
$resultado = Invoke-WebRequest -Method Post -Uri http://localhost:8000/books -body  $datos
$resultado.content

Salud2

Vale, la petición de tipo POST lo que hace es insertar un recurso en nuestra API REST.

También se puede usar array_push para insertar un dato al final del arreglo ^^

Documentación acerca del file_get_contents
https://www.php.net/manual/es/function.file-get-contents

me aparece este error:
Invoke-WebRequest : No se encuentra ningún parámetro que coincida con el nombre del parámetro ‘X’.
En línea: 1 Carácter: 6

  • curl -X ‘POST’ http://localhost:8000/books -d '{“titulo”: "Nuevo libr …
  •  ~~
    
    • CategoryInfo : InvalidArgument: (😃 [Invoke-WebRequest], ParameterBindingException
    • FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Me pueden ayudar?

Este es mi código en Python con FastAPI y Pydantic

Me encontre que como no cambie la ruta, osea que todavia tengo que mandar la url completa especificando los parametros no me mostraba nada, me di cuenta de esto a la mitad de del ejeercicio, les cuento esto para que aprendan a debugear y asi se daran cuenta que tanto han aprendido y lo que pueden reforzar es unexcelente ejercicio para comprender un poco mas el tema que estan viendo

a mi no me funcionaba el comando de curl hasta que lo usea así curl -H “Content-Type: application/json” -X POST -d “{ “titulo”:“Nuevo Libro”,“id_autor”: 1,“genero”: 2}” http://localhost:8000/books

Exelente y con estas bases ya estoy aprendiendo a prober los servicios en post man

Al realizar una peticion HTTP Post hay que enviar todos los datos necesarios para crear un recurso.

Con Go:

package main

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

var AllowedResources = map[string]bool{
	"books":   true,
	"authors": true,
	"genres":  true,
}

type Book struct {
	Titulo    string `json:"titulo"`
	Id_Autor  int    `json:"id_autor"`
	Id_gereno int    `json:"id_gereno"`
}

var Books = []Book{
	{
		Titulo:    "Lo que el viento se llevo",
		Id_Autor:  2,
		Id_gereno: 2,
	},
	{
		Titulo:    "El señor de los anillos",
		Id_Autor:  1,
		Id_gereno: 1,
	},
	{
		Titulo:    "La Odisea",
		Id_Autor:  1,
		Id_gereno: 3,
	},
}

func main() {
	http.Handle("/", http.HandlerFunc(ExampleHandler))
	http.HandleFunc("/books", books)
	http.HandleFunc("/book/", book)

	http.ListenAndServe(":8080", nil)
}

func book(w http.ResponseWriter, r *http.Request) {
	idstr := r.URL.Path[len("/book/"):]
	id, err := strconv.Atoi(idstr)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "<h1>Bad Request</h1>")
		return
	}

	switch r.Method {
	case http.MethodGet:
		getBook(w, r, id)
	case http.MethodDelete:
		w.Write([]byte("DELETE"))
	}
}

func getBook(w http.ResponseWriter, r *http.Request, id int) {
	// Get a single book
	maxBooks := len(Books)

	if id >= maxBooks {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprint(w, "<h1>Not Found</h1>")
		return
	}

	book := Books[id]
	response, err := json.Marshal(book)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprint(w, "<h1>Internal Server Error</h1>")
		return
	}

	fmt.Fprint(w, string(response))
}

func books(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		getBooks(w, r)
	case "POST":
		postBooks(w, r)
	}
}

func getBooks(w http.ResponseWriter, r *http.Request) {
	respose, err := json.Marshal(Books)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprint(w, "<h1>Internal Server Error</h1>")
		return
	}

	fmt.Fprint(w, string(respose))
}

func postBooks(w http.ResponseWriter, r *http.Request) {
	var book Book

	if err := r.ParseForm(); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "<h1>Bad Request</h1>")
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "<h1>Bad Request</h1>")
		return
	}

	if err := json.Unmarshal(body, &book); err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "<h1>Bad Request, error on unmarshal</h1>")
		return
	}

	Books = append(Books, book)
	w.WriteHeader(http.StatusCreated)
	fmt.Fprint(w, len(Books)-1)
}

Excelente curso, he probado en paralelo los verbos en Postman y funciona perfect!

Dejo este comentario para saber si a alguien le pasó lo mismo. Siempre miro varias veces el vídeo para tomar apuntes, entender y después hago el código. Logré los mismos resultados que el profesor a la hora de agregar contenido nuevo con POST. Mi problema o duda es la siguiente, luego de hacer lo que se muestra al final de este vídeo con resultados positivos, decidí hacer un get para que me traiga la información del arreglo $books y me trajo todo sin problemas menos la información nueva. Le pasó a alguien o soy yo el curioso? jajaja

Cuando iba a empezar este curso , aun tenia Windows, se me dificulto mucho. por este curso fue que decidí pasarme a Linux y la vida se me hizo mas sencilla.

Usen Git Bash, la solución a todos los problemas con CMD 😄

Buenas tardes, me gustaría saber como puedo hacer si me llegan demasiadas peticiones post y estas peticiones van a otro servicio socket y ya la respuesta del socket devolverla a la petición post pero que no se confunda las respuesta de estas.? Gracias

Incorporar datos a través de HTTP POST:
$ curl -X 'POST' http://localhost:8000/books -d '{ "titulo": "Nuevo Libro", "id_autor": 1, "id_genero": 2 }'
X ‘POST’: se usa el modificador -X y se especifica el pedido POST

  • d: modificador para indicar la información que se va a agregar

A mi me funcionó de esta manera:
curl -X POST http://localhost:8000/books -d “{ “titulo”: “Nuevo Libro”, “id_autor”: 2, “id_genero”: 4}”

Tengo curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL

Excelente contenido y explicación

Hasta acá llego, mi interés son las API. Si bien se puede aprender con cualquier lenguaje de programación, Python es mucho más amigable y claro, no me interesaba PHP…

uhmm… mi relación con php es nefasta, no me entra ni a palos. Mi primera experiencia fue horrible y desde ahí quedé traumado.

Quien necesita postman o insonmia cuando tiene curl 👨‍💻

super claro 😃

Para ejecutarlo es necesario comentar en server.php las lineas 10 12 15 y 16 para que pueda ejecutarse correctamente

He seguido el curso en Windows usando la consola de Git Bash. Facilita mucho las cosas en lugar de hacerlo por cmd.

<h1>Función para verificar si es un JSON (uno nunca se puede confiar)</h1>
function isJson( string $string ) : bool {
    json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE);
}
<h1>Implementación</h1>
$json = isJson( file_get_contents( 'php://input' ) ) ? json_decode( file_get_contents( 'php://input' ) ) : '';
print( isJson( file_get_contents( 'php://input' ) ) ? 'true' : 'false' );

if ( empty( $json ) ) {
	die();
} 

$books[] = $json;
// echo array_keys( $books )[count( $books ) - 1];
echo json_encode( $books );

excelente

POST:
curl -x ‘POST’ uri -d '{…'
x: Cambiar el tipo de envió
-d: El json a enviar

aqui les dejo como lo hice con python y flask

Esto funciono para mi en Windows…

curl -d '{\"title\": \"Frodo\",  \"id_author\" : \"Baggins\",\"id_gender\" : \"Thriller\" }' -H "Content-Type:application/json" -X POST http://localhost:8000/books```

Chicos, durante la prueba tuve un problema al ejecutar la instrucción

curl -X 'POST' http://localhost:8000/books -d '{"titulo": "Nuevo libro","id_autor": 1,"id_genero": 2 }'

por lo que tuve que comentar las siguientes lineas.

//$resourceType = $_GET[‘resource_type’];
//if( !in_array($resourceType, $allowedResourceTypes) ) {
// die;
//}

Al volver a ejecutar la instrucción funcionó devolviendo “4”

Espero que les sirva.
FYI