silverstripe / silverstripe-subsites

Subsites module for Silverstripe CMS
http://addons.silverstripe.org/add-ons/silverstripe/subsites
BSD 3-Clause "New" or "Revised" License
65 stars 106 forks source link

Running dev/build via CLI throws [Notice]: Undefined index: HTTP_HOST #437

Closed ChrissiQ closed 5 years ago

ChrissiQ commented 5 years ago

Because $_SERVER variables are not set in the CLI, the dev/build command thows a notice:

[1;31mERROR [Notice]: Undefined index: HTTP_HOST
IN GET dev/build
Line 189 in [path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php

Source
======
  180:     /**
  181:      * Retrieves domain name with wildcards substituted with actual values
  182:      *
  183:      * @todo Refactor domains into separate wildcards / primary domains
  184:      *
  185:      * @return string
  186:      */
  187:     public function getSubstitutedDomain()
  188:     {
* 189:         $currentHost = $_SERVER['HTTP_HOST'];
  190: 
  191:         // If there are wildcards in the primary domain (not recommended), make some
  192:         // educated guesses about what to replace them with:
  193:         $domain = preg_replace('/\.\*$/', ".{$currentHost}", $this->Domain);
  194: 
  195:         // Default to "subsite." prefix for first wildcard

Trace
=====
Monolog\ErrorHandler->handleError(8, Undefined index: HTTP_HOST, [path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php, 189, Array)
SubsiteDomain.php:189

SilverStripe\Subsites\Model\SubsiteDomain->getSubstitutedDomain()
ViewableData.php:133

SilverStripe\View\ViewableData->__get(SubstitutedDomain)
Subsite.php:874

SilverStripe\Subsites\Model\Subsite->domain()
ErrorPageSubsite.php:47

SilverStripe\Subsites\Extensions\ErrorPageSubsite->updateErrorFilename(error-404.html, 404, , , , , )
Extensible.php:468

SilverStripe\View\ViewableData->extend(updateErrorFilename, error-404.html, 404)
ErrorPage.php:399

SilverStripe\ErrorPage\ErrorPage::get_error_filename(404, SilverStripe\ErrorPage\ErrorPage)
ErrorPage.php:411

SilverStripe\ErrorPage\ErrorPage->getErrorFilename()
ErrorPage.php:268

SilverStripe\ErrorPage\ErrorPage->hasStaticPage()
ErrorPage.php:167

SilverStripe\ErrorPage\ErrorPage->requireDefaultRecordFixture(Array)
ErrorPage.php:140

SilverStripe\ErrorPage\ErrorPage->requireDefaultRecords()
DatabaseAdmin.php:382

SilverStripe\ORM\DatabaseAdmin->doBuild(, 1)
DatabaseAdmin.php:150

SilverStripe\ORM\DatabaseAdmin->build()
DatabaseAdmin.php:122

SilverStripe\ORM\DatabaseAdmin->index(SilverStripe\Control\HTTPRequest)
RequestHandler.php:323

SilverStripe\Control\RequestHandler->handleAction(SilverStripe\Control\HTTPRequest, index)
Controller.php:284

SilverStripe\Control\Controller->handleAction(SilverStripe\Control\HTTPRequest, index)
RequestHandler.php:202

SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)
Controller.php:212

SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)
DevBuildController.php:24

SilverStripe\Dev\DevBuildController->build(SilverStripe\Control\HTTPRequest)
RequestHandler.php:323

SilverStripe\Control\RequestHandler->handleAction(SilverStripe\Control\HTTPRequest, build)
Controller.php:284

SilverStripe\Control\Controller->handleAction(SilverStripe\Control\HTTPRequest, build)
RequestHandler.php:202

SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)
Controller.php:212

SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)
RequestHandler.php:226

SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)
Controller.php:212

SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)
Director.php:360

SilverStripe\Control\Director->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)
VersionedHTTPMiddleware.php:41

SilverStripe\Versioned\VersionedHTTPMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
InitStateMiddleware.php:44

SilverStripe\Subsites\Middleware\InitStateMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
DebugBarMiddleware.php:17

LeKoala\DebugBar\Middleware\DebugBarMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
ExecMetricMiddleware.php:20

SilverStripe\Control\Middleware\ExecMetricMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
ConfirmationMiddleware.php:246

SilverStripe\Control\Middleware\ConfirmationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
ConfirmationMiddleware.php:246

SilverStripe\Control\Middleware\ConfirmationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
BasicAuthMiddleware.php:68

SilverStripe\Security\BasicAuthMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
AuthenticationMiddleware.php:61

SilverStripe\Security\AuthenticationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
CanonicalURLMiddleware.php:190

SilverStripe\Control\Middleware\CanonicalURLMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
HTTPCacheControlMiddleware.php:42

SilverStripe\Control\Middleware\HTTPCacheControlMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
ChangeDetectionMiddleware.php:27

SilverStripe\Control\Middleware\ChangeDetectionMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
FlushMiddleware.php:27

SilverStripe\Control\Middleware\FlushMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
RequestProcessor.php:66

SilverStripe\Control\RequestProcessor->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
SessionMiddleware.php:20

SilverStripe\Control\Middleware\SessionMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
AllowedHostsMiddleware.php:60

SilverStripe\Control\Middleware\AllowedHostsMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
TrustedProxyMiddleware.php:176

SilverStripe\Control\Middleware\TrustedProxyMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
HTTPMiddlewareAware.php:65

SilverStripe\Control\Director->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)
Director.php:369

SilverStripe\Control\Director->handleRequest(SilverStripe\Control\HTTPRequest)
HTTPApplication.php:117

SilverStripe\Control\HTTPApplication::SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)

call_user_func(Closure, SilverStripe\Control\HTTPRequest)
HTTPApplication.php:136

SilverStripe\Control\HTTPApplication->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)
HTTPMiddlewareAware.php:65

SilverStripe\Control\HTTPApplication->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)
HTTPApplication.php:137

SilverStripe\Control\HTTPApplication->execute(SilverStripe\Control\HTTPRequest, Closure, 1)
HTTPApplication.php:118

SilverStripe\Control\HTTPApplication->handle(SilverStripe\Control\HTTPRequest)
cli-script.php:22

[2019-07-15 13:42:08] error-log.NOTICE: E_NOTICE: Undefined index: HTTP_HOST {"code":8,"message":"Undefined index: HTTP_HOST","file":"[path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php","line":189} []
PHP Notice:  Undefined index: HTTP_HOST in [path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php on line 189
[2019-07-15 13:42:08] error-log.NOTICE: E_NOTICE: Undefined index: HTTP_HOST {"code":8,"message":"Undefined index: HTTP_HOST","file":"[path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php","line":189} []
PHP Notice:  Undefined index: HTTP_HOST in [path]/vendor/silverstripe/subsites/src/Model/SubsiteDomain.php on line 189
robbieaverill commented 5 years ago

We may be able to refactor this to use an injectable HTTPRequest, and also build in a silent return if no request is set. Something like this:

- $currentHost = $_SERVER['HTTP_HOST'];
+ if (!Injector::inst()->has(HTTPRequest::class)) {
+     return '';
+ }
+ /** @var HTTPRequest $request */
+ $request = Injector::inst()->get(HTTPRequest::class);
+ $currentHost = $request->getHost();

Untested

robbieaverill commented 5 years ago

I've put this as impact/medium because I've never experienced this before, so it's probably harder to come across (do you have steps to reproduce?).

I'll note that some other server variables are set by HTTPRequestBuilder during the app startup, but HTTP_HOST doesn't appear to be one of them. I think we should replace its use in this code to avoid it the null pointer exception.

NightJar commented 5 years ago

As to steps to recreate, I'm going to hazard a guess that this is because an error page has been created for a subsite, which I believe isn't automatically created when adding a subsite which is likely why we've not come across it. These write a static cache to disk on flush, which means the page must render - with correct links. I get similar errors all the time because my webserver setup runs a different user to my login, although mine are permission errors, it seems the trace to get to that point is familiar to me.

  1. Have a project with subsites installed
  2. Create a subsite
  3. Create an error page for that subsite
    • possibly programmatically e.g. requireDefaultRecords or a BuildTask
  4. dev/build from the CLI.

Are you able to confirm please @ChrissiQ ?

Leapfrognz commented 5 years ago

I also get the same issue. SS4 CWP 2.3

robbieaverill commented 5 years ago

Would one of you mind providing steps to reproduce on a clean install please?

NightJar commented 5 years ago

Let's go on a journey

    "require": {
        "php": ">=5.6.0",
        "silverstripe/recipe-plugin": "^1.2",
        "silverstripe/recipe-cms": "4.4.x-dev",
        "silverstripe-themes/simple": "~3.2.0",
        "silverstripe/subsites": "2.3.x-dev"
    },

I have set up a subsite. By default, it has either no pages or a single page (this admittedly was an existing install for addressing another subsites issue - but I've reset to heads and composer update before proceeding)

image

I set up an error page. I have chosen 400, please ignore that this is inconsistent with my choice of Title (although this shouldn't matter; neither the code nor the title).

image

dev/build has completed successfully.

BUT

This has uncovered another bug, in that the error page has generated with the wrong domain.

image

Interestingly, when I do remove the domain from my Subsite definition (in the CMS), no page is generated at all. This is OK though.

So, how is my environment configured?

[vagrant@archlinux subfix]$ grep URL ../.env 
SS_BASE_URL="http://localhost:8080/"

Note though that the domain used in the static page generation is not matching this environment definition 🤔

Oh... whoops!

[vagrant@archlinux subfix]$ php -i | grep error
display_errors => Off => Off

Ah, but

[vagrant@archlinux subfix]$ grep -rin error_reporting vendor/silverstripe/framework/
vendor/silverstripe/framework/src/Core/CoreKernel.php:455:            error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE));
vendor/silverstripe/framework/src/Core/CoreKernel.php:458:            error_reporting(E_ALL | E_STRICT);

The second line is for sites not in live mode, and my environment is set to dev :)

[vagrant@archlinux subfix]$ grep -i environment_type ../.env 
SS_ENVIRONMENT_TYPE="dev"

So, a breakpoint in getSubstituteDomain shows that when building, this code is never called.

So, where are we so far?

NightJar commented 5 years ago

Got it. Thanks @Leapfrognz for providing more context (via Slack)

A subsite where Default site is true

This is the only criterion.

Reproduction:

robbieaverill commented 5 years ago

PR at #440

ScopeyNZ commented 5 years ago

440 is merged.

NZTA commented 5 years ago

After Director::host(); back, http_host issue is coming back. However, robbie's fix isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'; is working .. Can you please help why this is happened?

robbieaverill commented 5 years ago

@NZTA can you please clarify what you mean? Is the fix working or not working for you?

NZTA commented 5 years ago

@NZTA can you please clarify what you mean? Is the fix working or not working for you?

This is not working after changing to Director::host();.

robbieaverill commented 5 years ago

Can you clarify the problem you’re having? Are you seeing undefined index errors, does your dev/build break, does the subsite functionality break..?

satrun77 commented 5 years ago

Hi @robbieaverill

The fix in #440 merged into version 2.0 but does not exist from version 2.1

2.0: https://github.com/silverstripe/silverstripe-subsites/blob/2.0/src/Model/SubsiteDomain.php#L188 2.1: https://github.com/silverstripe/silverstripe-subsites/blob/2.1/src/Model/SubsiteDomain.php#L188

robbieaverill commented 5 years ago

@satrun77 thanks for letting me know. I've merged all the branches up. You can use a dev branch for now until a new version is tagged in each release line, e.g. 2.1.x-dev or 2.2.x-dev in your composer constraint for the subsites module.

robbyahn commented 5 years ago

Thanks, @satrun77. After running dev/build, it showed that undefined index errors under the subsite domain.

NightJar commented 5 years ago

@robbyahn please confirm:

  1. You have updated the composer dependency from a constraint (e.g. "silverstripe/subsites": "^2") to a dev version (e.g. "silverstripe/subsites": "2.2.x-dev")
  2. You have run a composer update
  3. Composer has updated silverstripe/subsites to 38b356c
  4. :eyes: You are still seeing the same error
robbyahn commented 5 years ago

@robbyahn please confirm:

  1. You have updated the composer dependency from a constraint (e.g. "silverstripe/subsites": "^2") to a dev version (e.g. "silverstripe/subsites": "2.2.x-dev")
  2. You have run a composer update
  3. Composer has updated silverstripe/subsites to 38b356c
  4. 👀 You are still seeing the same error

It was happened in cwp 2.3. Thanks, after merging, it is working good.

NightJar commented 5 years ago

Thanks for reporting back :) These adjustments will be released into CWP with the next quarterly release.