Cómo determinar de dónde proviene una solicitud en una API REST

4 minutos de lectura

avatar de usuario de frankelot
francolot

Tengo una API RESTful con controladores que deberían devolver una respuesta JSON cuando mi aplicación de Android la golpea y una “vista” cuando la golpea un navegador web. Ni siquiera estoy seguro de estar abordando esto de la manera correcta. Estoy usando Laravel y así es como se ve mi controlador

class TablesController extends BaseController {

    public function index()
    {
        $tables  = Table::all();

        return Response::json($tables);
    }
}

necesito algo como esto

class TablesController extends BaseController {

    public function index()
    {
        $tables  = Table::all();

        if(beingCalledFromWebBrowser){
            return View::make('table.index')->with('tables', $tables);
        }else{ //Android 
            return Response::json($tables);
        }
    }

¿Ves cómo las respuestas difieren entre sí?

Avatar de usuario de Shafi
Shafi

Nota::Esto es para futuros espectadores

El enfoque que encontré conveniente usando un prefijo api para llamadas api. En el uso del archivo de ruta

Route::group('prefix'=>'api',function(){
    //handle requests by assigning controller methods here for example
    Route::get('posts', 'Api\Post\PostController@index');
}

En el enfoque anterior, separo los controladores para llamadas api y usuarios web. Pero si quieres usar el mismo controlador entonces Laravel Request tiene una forma conveniente. Puede identificar el prefijo dentro de su controlador.

public function index(Request $request)
{
    if( $request->is('api/*')){
        //write your logic for api call
        $user = $this->getApiUser();
    }else{
        //write your logic for web call
        $user = $this->getWebUser();
    }
}

Él is El método le permite verificar que el URI de la solicitud entrante coincida con un patrón dado. Puedes usar el * carácter como comodín al utilizar este método.

  • Su respuesta es muy útil cuando usa un servicio como cloudflare. Porque noté que al hacer una solicitud http con ajax, cloudflare cambia los encabezados y, dado que Laravel determina si una solicitud espera json en función del valor en el encabezado Aceptar. Usar $request->is(‘api/*’) en lugar de $request->expectsJson() funcionó de maravilla para mí.

    – El más estúpido

    7 de noviembre de 2021 a las 14:04

Avatar de usuario de Unnawut
Unnawut

Puedes usar Request::wantsJson() Me gusta esto:

if (Request::wantsJson()) {
    // return JSON-formatted response
} else {
    // return HTML response
}

Básicamente lo que Request::wantsJson() lo que hace es comprobar si el accept el encabezado de la solicitud es application/json y devolver verdadero o falso en función de eso. Eso significa que deberá asegurarse de que su cliente también envíe un encabezado “aceptar: aplicación/json”.

Tenga en cuenta que mi respuesta aquí no determina si “una solicitud proviene de una API REST”, sino que detecta si el cliente solicita una respuesta JSON. Sin embargo, mi respuesta debería ser la forma de hacerlo, porque el uso de la API REST no significa necesariamente que se requiera una respuesta JSON. La API REST puede devolver XML, HTML, etc.


Referencia a Laravel Iluminar\Http\Solicitar:

/**
 * Determine if the current request is asking for JSON in return.
 *
 * @return bool
 */
public function wantsJson()
{
    $acceptable = $this->getAcceptableContentTypes();

    return isset($acceptable[0]) && $acceptable[0] == 'application/json';
}

  • La cosa es que no uso ajax para todas mis solicitudes cuando presiono la API desde el navegador. ¿debería?

    – Frankelot

    5 de julio de 2014 a las 21:20

  • Bien, he modificado mi respuesta. Deberá asegurarse de que su aplicación solicite json configurando accept encabezado en la solicitud de “aplicación/json”. Se actualizará en un momento de cómo funciona internamente.

    – Unnawut

    5 de julio de 2014 a las 21:26


Usa este Camino. simplemente puede identificar la URL como formulario de llamada (Web o API)

Código del controlador

if ( Request::capture()->expectsJson()  )
     {  return "API Method";  }
     else
     {  return "Web Method";     }

Código de ruta

Para api.php Route::post(“category”,”CategoryController@index”);

Para Web.php Route::get(“category”,”CategoryController@index”);

Puedes usar

if ($request->wantsJson()) {
     // enter code heree
}

¿Su aplicación utiliza encabezados o tokens de autorización diferentes? Si es así, puede crear una función de ayuda para verificar los encabezados en busca de una clave. Nuestra aplicación envía un encabezado de Autorización (para el pasaporte) mientras que nuestro extremo web usa la cookie web del pasaporte en la sesión web, así que solo busco la clave de Autorización para saber que es la aplicación:

if(request()->hasHeader('Authorization')){
//is from app
}

Avatar de usuario de Sprep
Sprepar

Nada de esto funcionó para mí porque tenía una estructura de ruta diferente.

Uno podría hacerlo así también.

public function __construct(Request $request) {
    $this->request = $request;
    $this->isApi = $this->request->segment(1) === 'api' ? true : false;
}

Luego, utilícelo así en su controlador.

if($this->isApi){
  //do things for api view
} else {
 //do things for html view
}

Espero eso ayude.

Avatar de usuario de Imran
Imrán

You can easily check the route that came from either web or API with this.

if($request->route()->getPrefix() === 'api') {
   // Your logic
}

¿Ha sido útil esta solución?