Single end point REST API I want to ask question about a better way for implementing single endpoint REST.
I want to build a rest API but I want it to only have single endpoint like: graphql, where you only have like: host/graphql.
I already doing this example in laravel where you need to put a key and method to go to a certain API.
The body look like this (example of calling product API with single endpoint).
Calling get all product:
    {
     &quot;key&quot;:&quot;product/all&quot;,
     &quot;method&quot;:&quot;GET&quot;
    }

And this is the get one (product/{id}):
    {
    &quot;key&quot;:&quot;product&quot;,
    &quot;method&quot;:&quot;GET&quot;,
    &quot;payload&quot;:&quot;{\&quot;id\&quot;:\&quot;1\&quot;}&quot;
    }

This is also work fine with post, put and delete.
Here is the single endpoint code (I use php laravel as example because it fast to make API):
    public function bridge(Request $request)
    {

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

As you can see there. It is calling the API twice &quot;bridge&quot; and the &quot;key&quot; API.
The cons here:

call request twice;
you can only put one /{id} variable (or more if you declare it).

Pros:

it only one endpoint so it will be easy to make an api helper in the frontend (maybe XD).

Can you show me a better way of doing this?
Tell me your tips and thought or maybe show some code (any language is fine).
I only have a few quibbling remarks:

Don't Repeat Yourself (D.R.Y.)

Declare $url = $host . $request-&gt;key unconditionally at the start of your method (say, after $host).  Then append text to it if/when needed $url .= '/' . $payload['id'];.
strtoupper($request-&gt;method) is done in each conditional expression.  It is better practice to mutate the string once.  You're also checking the same data for different strings, this is what switch-case blocks are for.
Rather than writing $data (a non-descriptive variable name) over and over, omit the variable declaration entirely and write the data directly into the return.  I regularly advise against single-use variable declarations unless they valuably reduce code width or improve readability.


else if should be elseif in PHP to comply with the PSR-12 coding standard.
All of your thrown exceptions are handled identically, so it seems to be a much cleaner choice to wrap your whole switch block in a single try-catch block.
Maybe you'd like to see the payload when there is a thrown exception; if so, use &quot;data&quot; =&gt; $payload ?? [] in the return.

Your code might be rewrite as:
public function bridge(Request $request)
{
    $host = &quot;http://127.0.0.1:8000/api/&quot;;
    $url = $host . $request-&gt;key;

    if ($request-&gt;has(&quot;payload&quot;)) {
        $payload = json_decode(html_entity_decode($request-&gt;payload), true);
    }

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