Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subdirectory installs: API urls are not generated correctly #202

Closed
ghost opened this issue Jun 27, 2018 · 10 comments
Closed

Subdirectory installs: API urls are not generated correctly #202

ghost opened this issue Jun 27, 2018 · 10 comments

Comments

@ghost
Copy link

ghost commented Jun 27, 2018

If the Laravel application is installed in a subdirectory, URLs (e.g. self and related) are generated relative to the domain rather than the application URL.

Consider an API being served from https://example.org/app/ with the following default configuration in config/json-api-default.php.

  'url' => [
        'host' => null,
        'namespace' => '/api/v1',
        'name' => 'api:v1:',
    ],

API results look like:

HTTP/1.1 200 OK
Content-Type application/vnd.api+json

{
    "data": [
        {
            "type": "posts",
            "id": "1",
            "attributes": {
                "title": "My First Post",
                "slug": "my-first-post"
            },
            "links": {
                "self": "https://example.org/api/v1/posts/1"
            }
        },
        {
            "type": "posts",
            "id": "2",
            "attributes": {
                "title": "Hello World",
                "slug": "hello-world"
            },
            "links": {
                "self": "https://example.org/api/v1/posts/2"
            }
        }
    ]
}

The links should respect the application URL and be of the form https://example.org/app/api/v1/posts/2.

It seems that this issue may be caused by the use of getSchemeAndHttpHost() from the Symfony HttpFoundation package in Http\Middleware\BootJsonApi.php (lines 77 and 78).

/** Build and register the API */
$api = $this->bindApi($namespace, $request->getSchemeAndHttpHost());

If we set the second argument to null, urls are generated correctly.

/** Build and register the API */
$api = $this->bindApi($namespace, null);
@lindyhopchris
Copy link
Member

Hi! Surely your namespace setting should be /app/api/v1 because that is your API's namespace on the host?

@lindyhopchris
Copy link
Member

Or alternatively, what Laravel settings are you using to tell Laravel that it is hosted under the app/ folder?

@lindyhopchris
Copy link
Member

Would seem that this needs to be supported, but we cannot removed the detection of the host because otherwise it will break the host working correctly on wildcard sub-domains. Changing that line to pass a second argument as null would break that use case.

@ghost
Copy link
Author

ghost commented Jun 28, 2018

Yes, absolutely. setting namespace to /app/api/v1 solves the problem. However, because config/json-api-default.php is committed to version control for a given Laravel app, it makes it awkward to manage installations of the same application on different servers where it may be installed in different directories. This might be a less common use case though!

@lindyhopchris
Copy link
Member

If the namespace is going to vary per installation, then using an ENV setting would be most appropriate. E.g. set the namespace configuration option to:

'namespace' => env('JSON_API_NAMESPACE', '/app/api/v1')

It would help me out though if you could tell me how you handle normal routing. E.g. if your application had a /home endpoint within its sub-directory, how would you define that using Laravel routing? Are you doing the following or something else...

Route::get('/app/home', 'HomeController@home');

@ghost
Copy link
Author

ghost commented Jun 29, 2018

Using an ENV setting is an excellent idea, thank you! I can't believe I didn't think of that.

I am going do some testing just now as I note that CloudCreativity\LaravelJsonApi\Api\Repository::createApi is called twice upon visiting an endpoint. Once with no $host value (CloudCreativity\LaravelJsonApi\Routing\ResourceRegistrar::api) and then once with a host value (CloudCreativity\LaravelJsonApi\Http\Middleware\BootJsonApi::bindApi).

As for normal routing, I am using the following.

Route::get('/home', 'HomeController@home');

@ghost
Copy link
Author

ghost commented Jun 29, 2018

Using an ENV setting caused routing errors.

I propose an alternative solution combining Symfony's getBaseUrl with getSchemeAndHttpHost: #204

@lindyhopchris
Copy link
Member

Thanks for investigating this. Can't see how to add tests for it unfortunately so have just merged it for the moment as it doesn't break any existing stuff as far as I can see.

In terms of createApi being called twice. In development that will be once for the JSON API routes being registered and once for the actual request being processed. In production it would only be called once if you've used route caching.

I'm planning to release this change and another as v1.0.0-alpha.4 but need to hear back about another issue before tagging. If you want to use in the meantime, then use the following:

composer require cloudcreativity/laravel-json-api:dev-master

I don't make breaking changes to master so it's safe to use until I tag.

@lindyhopchris
Copy link
Member

Released in v1.0.0-alpha.4

@ghost
Copy link
Author

ghost commented Jul 2, 2018

Thank you for resolving this so quickly. Much appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant