REST API с единой конечной точкой

Я хочу задать вопрос о том, как лучше реализовать REST с одной конечной точкой.

Я хочу создать API отдыха, но хочу, чтобы у него была только одна конечная точка, например: graphql, где у вас есть только лайки: host/graphql.

Я уже делал этот пример в laravel где нужно поставить ключ и метод для перехода к определенному API.

Тело выглядит так (пример вызова API продукта с единственной конечной точкой).

Звонок получить весь товар:

    {
     "key":"product/all",
     "method":"GET"
    }

Вот и получилось (product / {id}):

    {
    "key":"product",
    "method":"GET",
    "payload":"{"id":"1"}"
    }

Это также отлично работает с публикацией, помещением и удалением.

Вот код единственной конечной точки (я использую php laravel в качестве примера, потому что быстро сделать API):

    public function bridge(Request $request)
    {

        $host = "http://127.0.0.1:8000/api/";
        if ($request->has("payload")) {
            $bounds = html_entity_decode($request->payload);
            $payload = json_decode($bounds, true);
        }
        if (strtoupper($request->method) == "POST") {
            try {
                $url = $host . $request->key;
                $request = Request::create($url, 'POST', []);
                $response = Route::dispatch($request);
                return $response;
            } catch (Throwable $th) {
                $data["data"] = [];
                $data["success"] = false;
                $data["code"] = 500;
                $data["message"] = $th->getMessage();
                return $data;
            }
        } else if (strtoupper($request->method) == "PUT") {
            try {
                $url = $host . $request->key . "https://codereview.stackexchange.com/" . $payload['id'];
                $request = Request::create($url, 'PUT', []);
                $response = Route::dispatch($request);
                return $response;
            } catch (Throwable $th) {
                $data["data"] = [];
                $data["success"] = false;
                $data["code"] = 500;
                $data["message"] = $th->getMessage();
                return $data;
            }
        } else if (strtoupper($request->method) == "DELETE") {
            try {
                $url = $host . $request->key . "https://codereview.stackexchange.com/" . $payload['id'];
                $request = Request::create($url, 'DELETE', []);
                $response = Route::dispatch($request);
                return $response;
            } catch (Throwable $th) {
                $data["data"] = [];
                $data["success"] = false;
                $data["code"] = 500;
                $data["message"] = $th->getMessage();
                return $data;
            }
        } else {
            $url = $host . $request->key;
            try {
                if ($request->has("payload")) {
                    $url = $host . $request->key . "/" . $payload['id'];
                }
                $request = Request::create($url, 'GET');
                $response = Route::dispatch($request);
                return $response;
            } catch (Throwable $th) {
                $data["data"] = [];
                $data["success"] = false;
                $data["code"] = 500;
                $data["message"] = $th->getMessage();
                return $data;
            }
        }
    }

Как видите там. Он вызывает API дважды «мост» и «ключевой» API.

Минусы тут:

  • запрос звонка дважды;
  • вы можете поместить только одну переменную / {id} (или несколько, если вы ее объявите).

Плюсы:

  • это только одна конечная точка, поэтому будет легко создать помощник api во внешнем интерфейсе (возможно, XD).

Вы можете показать мне лучший способ сделать это? Расскажите мне свои советы и мысли или, может быть, покажите какой-нибудь код (любой язык подойдет).

1 ответ
1

У меня есть только несколько замечаний по поводу придирчивости:

  • Не повторяйся (СУХОЙ)
    • Объявить $url = $host . $request->key безусловно в начале вашего метода (скажем, после $host). Затем добавьте к нему текст, если / когда необходимо $url .= "https://codereview.stackexchange.com/" . $payload['id'];.
    • strtoupper($request->method) выполняется в каждом условном выражении. Лучше изменить строку один раз. Вы также проверяете одни и те же данные для разных строк, вот что switch-case блоки предназначены для.
    • Вместо того, чтобы писать $data (не описательное имя переменной) снова и снова, полностью опускайте объявление переменной и записывайте данные непосредственно в return. Я регулярно рекомендую не объявлять одноразовые переменные, если они существенно не уменьшают ширину кода или не улучшают читаемость.
  • else if должно быть elseif в PHP, чтобы соответствовать стандарту кодирования PSR-12.
  • Все созданные вами исключения обрабатываются одинаково, поэтому кажется гораздо более чистым вариантом обернуть весь ваш блок переключателя в один try-catch блокировать.
  • Возможно, вы захотите увидеть полезную нагрузку при возникновении исключения; если да, используйте "data" => $payload ?? [] в ответ.

Ваш код может быть переписан как:

public function bridge(Request $request)
{
    $host = "http://127.0.0.1:8000/api/";
    $url = $host . $request->key;

    if ($request->has("payload")) {
        $payload = json_decode(html_entity_decode($request->payload), true);
    }

    try {
        switch (strtoupper($request->method)) {
            case "POST":
                return Route::dispatch(Request::create($url, 'POST', []));
            case "PUT":
                $url .= "https://codereview.stackexchange.com/" . $payload['id'];
                return Route::dispatch(Request::create($url, 'PUT', []));
            case "DELETE":
                $url .= "https://codereview.stackexchange.com/" . $payload['id'];
                return Route::dispatch(Request::create($url, 'DELETE', []));
            default:
                if ($request->has("payload")) {
                    $url .= "/" . $payload['id'];
                }
                return Route::dispatch(Request::create($url, 'GET'));
         }
     } catch (Throwable $th) {
         return [
                    "data" => $payload ?? [],
                    "success" => false,
                    "code" => 500,
                    "message" => $th->getMessage(),
                ];
     }
}

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *