storyblok-nuxt icon indicating copy to clipboard operation
storyblok-nuxt copied to clipboard

Add option to specify the region (or clarify how to specify)

Open michaelvcolianna opened this issue 1 year ago • 1 comments

With the release of V2, some users need to specify the region in the URL for requests (see https://www.storyblok.com/docs/api/content-delivery/v2). If that new URL isn't used, the only response from the API will be an unauthorized error. The regular JS API has a way to specify the region in the config, but passing that option with this Nuxt module doesn't appear to have an effect.

To see the issue I'm describing, go to the StackBlitz demo and swap the API key with Bwjx9SX0d0B9EwSTcnpQNAtt. (This key is from a brand new space.) Among the errors it spits out, you'll see [nuxt] [request error] Request failed with status code 401 which corresponds with the message received if you try a cURL request:

curl "https://api.storyblok.com/v2/cdn/stories?token=Bwjx9SX0d0B9EwSTcnpQNAtt" \
-X GET \
-H "Accept: application/json" \
-H "Content-Type: application/json"

Returns {"error":"Unauthorized"}

vs:

curl "https://api-us.storyblok.com/v2/cdn/stories?token=Bwjx9SX0d0B9EwSTcnpQNAtt" \
-X GET \
-H "Accept: application/json" \
-H "Content-Type: application/json"

Returns data.

It's entirely possible I'm missing how/where to add the region option, so apologies if so. I just ran into the problem trying to create a new project following the "Add a headless CMS to Nuxt 3 in 5 minutes" tutorial.

Please advise if there's other information I should attach. I figured the StackBlitz example was enough since I was unable to complete the tutorial and what I have is the exact same code.

michaelvcolianna avatar Aug 06 '22 18:08 michaelvcolianna

Have you had any luck getting this to work

clpowe avatar Aug 23 '22 23:08 clpowe

@clpowe Apologies, I don't seem to be getting notifications. I haven't seen any updates from my chat w/Storyblok support but I also don't know whether they interface with the devs on this project.

What I found is that if you create a new blank space, you end up in the "US" region and needing to use the region preface with the API.

If you create a new space using the example site, you end up in the "EU" region and don't need to use the preface with the API.

The easiest ways to tell are in the listing of your spaces, the bottom right will say "EU" or "US" (I'm not sure if there are other region possibilities) OR you'll see a "Back to V1" link at the bottom of the menu on the left side.

Hope that helps!

michaelvcolianna avatar Aug 31 '22 13:08 michaelvcolianna

No worries thanks for the reply. I will take a look. I'm in the US so I do want to use the US based servers.

clpowe avatar Sep 01 '22 21:09 clpowe

Oh boy! I went down a deep-rabbit hole trying to figure this out. So in theory its super easy (spoiler it was not 😠). You are able to pass an option into the configuration apart from the accessToken exactly for this purpose: { apiOptions: { region: 'us' }. However, this is where the fun begins. As we can see from the plugin file, a nuxt plugin is loaded to run a vue plugin using the configuration retrieved with useRuntimeConfig. The issue is that according to nuxt:

The entire runtime config is available on the server-side, but it is read-only to avoid context sharing. source

This becomes an issue because the following configuration gives the error: Cannot add property accessToken, object is not extensible

{
  "accessToken": "<your access token>",
  "apiOptions": { "region": "us" }
}

There is an additional way to pass the accessToken inside the apiOptions directly (source), however that gives a different error: Cannot assign to read only property 'accessToken' of object '#<Object>'

😭

But fear not, for there is hope! 🕊️ An additional configuration option can be specified when you want to provide your own plugin and to stop using the default one: usePlugin: false. We just need to copy the existing plugin into a local plugin and make a deep copy of the configuration before passing it to @storyblok/vue - in this case using JSON.parse(JSON.stringify(storyblok)).

Files

plugins/storybook.ts

import { StoryblokVue, apiPlugin } from "@storyblok/vue";
import { defineNuxtPlugin, useRuntimeConfig } from "#app";

export default defineNuxtPlugin(({ vueApp }) => {
  const { storyblok } = useRuntimeConfig();
  const deepCopy = JSON.parse(JSON.stringify(storyblok));
  deepCopy.use = [apiPlugin]
  vueApp.use(StoryblokVue, deepCopy);
});

nuxt.config.ts

import { defineNuxtConfig } from 'nuxt'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
   modules: [
      "@storyblok/nuxt",
      '@nuxtjs/tailwindcss',
   ],
   storyblok: {
      accessToken: "<your access token>",
      apiOptions: { region: 'us' },
      usePlugin: false,
   }
})

Result

And voila! It now works properly. Screenshot from 2022-09-01 22-53-49

StaffOfHades avatar Sep 02 '22 04:09 StaffOfHades

Hi @michaelvcolianna and everyone. Good news, just pushed the fix for this 🚀 Please upgrade to latest version v4.3.0 and it should work.

alexjoverm avatar Sep 07 '22 15:09 alexjoverm

@alexjoverm it took you guys quite a while, but thank you for fixing this issue. It now works as expected :)

rodrigodagostino avatar Sep 07 '22 17:09 rodrigodagostino