bigcommerce / stencil-cli

BigCommerce Stencil emulator for local theme development
https://developer.bigcommerce.com/stencil-docs
BSD 4-Clause "Original" or "Old" License
102 stars 141 forks source link

Local Development for "Maintenance" page results in unhandled 500 Error #1119

Open LanetheGreat opened 1 year ago

LanetheGreat commented 1 year ago

Expected behavior

When setting the default storefront (Channel 1) of a webstore to Inactive (maintenance mode) and navigating to the URL http://localhost:3000/?showStore=no the local template templates/pages/unavailable/maintenance.html is expected to be rendered like any other page.

Actual behavior

After setting the webstore setting and navigating to the URL http://localhost:3000/?showStore=no to preview the maintenance page template locally, it results in stencil's default unhandled error JSON:

{"statusCode":500,"error":"Internal Server Error","message":"An internal server error occurred"}

Plus the console for stencil-cli outputs this during the error:

Debug: internal, implementation, error
    [Cannot display object: Converting circular structure to JSON
    --> starting at object with constructor 'TLSSocket'
    |     property 'parser' -> object with constructor 'HTTPParser'
    --- property 'socket' closes the circle]

Steps to reproduce behavior

  1. Update a sandbox webstore's default storefront channel to Inactive
  2. Install @bigcommerce/stencil-cli either from npmjs.org or locally from a git clone && npm link
  3. Configure stencil-cli as normal for local development with the API token
  4. Navigate to http://localhost:3000/?showStore=no

Environment

Stencil-cli version stencil --version: 7.2.0 (latest at the time of this issue) Node version node -v: v18.16.0 NPM version npm -v: 9.5.1 OS: Windows (but issue is OS independent)

Comments

I managed to locate the issue in stencil-cli with how it lets axios handle the 503 response returned from the API request by throwing an Error instead of allowing it with the validateStatus option in the following file: https://github.com/bigcommerce/stencil-cli/blob/d5b910377774f6aebc11c5ef9c49f027febc3f2c/server/plugins/renderer/renderer.module.js#L81-L96 Reusing the query parameters extracted prior and checking the status code I was able to make a quick patch that fixes the issue for me (and still allows other unexpected 503's to be handled by axios's default error throw):

    const withoutPageQuery = new URL(fullUrl.toString());
    withoutPageQuery.searchParams.delete('page');

    const httpOpts = {
        url: withoutPageQuery.toString(),
        headers: internals.buildReqHeaders({
            request,
            stencilOptions: { get_template_file: true, get_data_only: true },
            extraHeaders: { host: storeUrlObj.host },
        }),
        accessToken: internals.options.accessToken,
        data: request.payload,
        method: request.method,
        maxRedirects: 0, // handle the redirects manually to handle the redirect location
        // If the response is an image it will be parsed wrongly, so we receive a raw data (stream)
        //  and perform it manually depending on contentType later
        responseType: 'stream',
        validateStatus: (status) =>
            (status >= 200 && status < 500) ||
            (status === 503 && withoutPageQuery.searchParams.get('showStore') === 'no'),
    };

But I don't have the time nor the experience yet to make a full patch or Jest test case since I think it uses a reserved store https://store-abc123.mybigcommerce.com/ for testing and a store that's in maintenance mode would be needed in order to properly test this scenario, I think?