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

JS fetch request works from Craft frontend, but not from a different subdomain #182

Open
Michael-Paragonn opened this issue Aug 9, 2023 · 0 comments
Labels

Comments

@Michael-Paragonn
Copy link

Michael-Paragonn commented Aug 9, 2023

Description

A client has an Element API endpoint set up to return quick "as you type" search results. This works beautifully from the Craft site (https://example.com).

The client also has a subdomain powered by HubSpot (https://learn.example.com), and they want the same functionality across both sites. But when I copy over the same exact JS, the returned response is supposedly a 404, even though the JSON payload is identical.

Any ideas on why it's not working from a subdomain? I do have Access-Control-Allow-Origin defined properly, and I do see the difference it makes when it's there vs not there...

element-api.php

<?php
use craft\elements\Entry;

return
[
    'endpoints' =>
    [
        'api/search' => function()
        {
            Craft::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Origin', 'https://learn.example.com');
            Craft::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Credentials', true);

            // settings
            $section_handle = 'about, blog, caseStudies, industries, services, work';
            $phrase = Craft::$app->request->getParam('query');

            $criteria = [
                'section' => $section_handle,
                'limit' => 5,
                'orderBy' => 'score',
                'search' => $phrase,

            ];

            return [
                'elementType' => Entry::class,
                'criteria' => $criteria,
                'paginate' => false,
                'transformer' => function(craft\elements\Entry $entry)
                {

                    return [
                        'title' => $entry->title,
                        'url' => $entry->section->handle == 'blog' ? $entry->permalink : $entry->url,
                        'section' => $entry->section->name,
                    ];
                },

            ];
        },
    ]
];

JS search functionality (on the HubSpot subdomain site):

function delay(fn, ms)
{
    let timer = 0
    return function(...args)
    {
        clearTimeout(timer)
        timer = setTimeout(fn.bind(this, ...args), ms || 0)
    }
}
let searchAutocompleteInputs = document.querySelectorAll('.jsSearchAutocomplete');
searchAutocompleteInputs.forEach(input =>
{
    let autocompleteId = input.dataset.list;
    let autocomplete = document.getElementById(autocompleteId);
    input.addEventListener('input', delay( function(e)
    {
        let keyword = e.target.value;
        if (keyword)
        {
            fetch('https://example.com/api/search' + `?query=${keyword}`, {mode: 'cors'})
            .then((response) =>
            {
                console.log({response});
                if (response.ok)
                {
                    return response.json();
                }
                throw new Error('Something went wrong with the fetch');
            })
            .then( (responseJson) =>
            {
                               // blah blah...
            })
            .catch((error) =>
            {
                console.warn(error);
            });
        }
        // Empty search field
        else
        {
            autocomplete.innerHTML = '';
        }
    }, 500));
});

"404" response from Hubspot site:

# General
- Request URL: https://example.com/api/search?query=logo
- Request Method: GET
- Status Code: 404
- Remote Address: [redacted]:443
- Referrer Policy: no-referrer-when-downgrade
# Response Headers
- Access-Control-Allow-Credentials: 1
- Access-Control-Allow-Origin: https://learn.example.com
- Cf-Cache-Status: DYNAMIC
- Cf-Ray: 7f43074238c72bca-FRA
- Content-Encoding: br
- Content-Type: application/json; charset=UTF-8
- Date: Wed, 09 Aug 2023 21:17:52 GMT
- Link: <https://example.com/api/search>; rel="canonical"
- Nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
- Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=blahblahblah"}],"group":"cf-nel","max_age":604800}
- Server: cloudflare
- Vary: Accept-Encoding
- X-Powered-By: Craft CMS
- X-Robots-Tag: none
# Request Headers
- :authority: example.com
- :method: GET
- :path: /api/search?query=logo
- :scheme: https
- Accept: */*
- Accept-Encoding: gzip, deflate, br
- Accept-Language: en-US,en;q=0.9,he;q=0.8,ar;q=0.7
- Origin: https://learn.example.com
- Referer: https://learn.example.com/?hsDebug=true
- Sec-Ch-Ua: "Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"
- Sec-Ch-Ua-Mobile: ?0
- Sec-Ch-Ua-Platform: "Windows"
- Sec-Fetch-Dest: empty
- Sec-Fetch-Mode: cors
- Sec-Fetch-Site: same-site
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36

Valid response from the Craft site:

# General
- Request URL: https://example.com/api/search?query=logo
- Request Method: GET
- Status Code: 200
- Remote Address: [redacted]:443
- Referrer Policy: strict-origin-when-cross-origin
# Response Headers
- Access-Control-Allow-Credentials: 1
- Access-Control-Allow-Origin: https://learn.example.com
- Cache-Control: no-store, no-cache, must-revalidate
- Cf-Cache-Status: DYNAMIC
- Cf-Ray: 7f4301de1ad82bc1-FRA
- Content-Encoding: br
- Content-Type: application/json; charset=UTF-8
- Date: Wed, 09 Aug 2023 21:14:11 GMT
- Expires: Thu, 19 Nov 1981 08:52:00 GMT
- Link: <https://example.com/api/search>; rel="canonical"
- Nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
- Pragma: no-cache
- Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=blahblah"}],"group":"cf-nel","max_age":604800}
- Server: cloudflare
- Set-Cookie: blahblah expires=Wed, 23-Aug-2023 21:14:11 GMT; Max-Age=1209600; path=/; secure; HttpOnly
- Vary: Accept-Encoding
- X-Debug-Duration: 211
- X-Debug-Link: https://example.com/actions/debug/default/view?tag=64d401a3b341e
- X-Debug-Tag: 64d401a3b341e
- X-Powered-By: Craft CMS
- X-Robots-Tag: none
# Request Headers
- :authority: example.com
- :method: GET
- :path: /api/search?query=logo
- :scheme: https
- Accept: */*
- Accept-Encoding: gzip, deflate, br
- Accept-Language: en-US,en;q=0.9,he;q=0.8,ar;q=0.7
- Cookie: blahblah
- Referer: https://example.com/
- Sec-Ch-Ua: "Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"
- Sec-Ch-Ua-Mobile: ?0
- Sec-Ch-Ua-Platform: "Windows"
- Sec-Fetch-Dest: empty
- Sec-Fetch-Mode: cors
- Sec-Fetch-Site: same-origin
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36

Additional info

  • Craft version: Craft CMS 3.7.55.2
  • PHP version: 7.4.33
  • Database driver & version: MySQL 8.0.30
  • Plugins & versions:
    • Advanced Image Field 1.0.0
    • Button Box 3.1.1
    • Contact Form 2.5.1
    • Contact Form Honeypot 1.0.3
    • Control Panel CSS 2.4.0
    • Digital Download 2.1.9
    • DigitalOcean Spaces Volume 1.1.3
    • Element API 2.8.6.1
    • Feed Me 4.6.3.1
    • Field Manager 2.2.5
    • Forms 3.13.20
    • Guest Entries 2.4.0
    • Imager X v3.6.5
    • Imager X Storage Driver for DigitalOcean Spaces 2.0.0
    • Inventory 2.1.1
    • [Custom Plugin]1.0.0
    • Mix 1.5.2
    • Neo 2.13.15
    • oEmbed 1.3.18
    • Postmark 2.1.0
    • Redactor 2.10.10
    • Redactor Custom Styles 3.0.4
    • Redirects 3.2.10
    • Scout 2.7.2
    • SEO 3.7.4
    • Sprout Email 4.4.10
    • Super Table 2.7.3
    • Typed link field 1.0.25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant