Conditionally tell of `.astro` component is being used as a route or component - astrojs

Within the AstroJS framework (https://astro.build/) you can have .astro files that are route, you can also import these files into other astro files and use them as components. I've seen an issue that depending on what Astro.request properties are called, you're only allow to call them when the file is used as a route. Is it possible to conditionally know if the file is a route or a component?

Response difference
I found a way how to differentiate the route from the component which is by looking at the response. The reason is that the response is sent at the end of the route frontmatter and before the components frontmatter, that's why the header list is going to have more entries.
Although this is possible, I recommend to differentiate between routes and components by design, such as adding properties with default values not to rely on the response structure. Also the response is not to be used by child components but only by the route, this allows Astro to have an optimized stream response.
reference ( caution section https://docs.astro.build/en/guides/server-side-rendering/#astrorequestheaders)
response log in route and in component
{
status: 200,
statusText: 'OK',
headers: HeadersList {
[Symbol(headers map)]: Map(1) { 'content-type' => 'text/html' },
[Symbol(headers map sorted)]: null
}
}
{
status: 200,
statusText: 'OK',
headers: HeadersList {
[Symbol(headers map)]: Map(1) { 'content-type' => 'text/html' },
[Symbol(headers map sorted)]: Map(1) { 'content-type' => 'text/html' }
}
}
Clarifications
talking about routes, assumed mode is SSR
Not talking about integration API but about SSR components runtime API https://docs.astro.build/en/reference/api-reference/
It is possible for '.astro' file to be both a component and a route when let's say a pages/404.astro is a route but is also used by a component from pages/[...any].astro
That nasty case would not allow to check the path where it is in with import.meta.url so it could be in pages even if used as component for another route.
Test of Request similarity
route = [...any].astro
component = pages/404.astro
in each of them the following log is placed
console.log(Astro.request)
console.log(Astro.request.headers)
console.log(Astro.url)
console.log(Astro.params)
console.log(Astro.props)
the test is performed with a single request call (page load) where the execution goes first through 404.astro when it is imported then through [...].astro when its frontmatter is executed.
The log is then compared with a diff tool

Related

How do I log a specific field in API requests within Cypress

I want to cypress.log() out a specific field in the request header whenever my webapp makes requests that way when it fails and adds screenshots/logs I can grab that that requestId that failed.
Is there a way to setup cypress so that for all network requests it checks for this field and log it?
I can add a cy.intercept within each individual file but I want a more generic way to handle this.
Cypress.log is the synchronous version of cy.log().
Add middleware: true to the intercept to pass request to other intercepts.
cy.intercept({ url: '*', middleware: true }, (req) => {
const headerValue = req.headers?['x-custom-headers']
if (headerValue) {
Cypress.log({
name: 'x-custom-header',
message: headerValue
})
}
})
You'll get an Cypress promise error if you try to use cy.log() to log out every request header in an cy.intercept() within a routeHandler callback. This would also make it kind of tough to log to a CI terminal as well.
Instead you can console.log to dev tools. To make it apply to all tests, you can wrap it in a beforeEach() and place it in the support/index.js file.
// support/index.js
beforeEach(() => {
cy.intercept('*', (req) => {
req.continue((res) => {
console.log(JSON.stringify(req.headers))
})
})
})

How to intercept Playwright's Firefox image requests

I recently tried to intercept all image requests following the example in their documentation:
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Abort based on the request type
await page.route('**/*', route => {
return route.request().resourceType() === 'image' ?
route.abort() : route.continue();
});
But it was not working at all.
How can I make it work?
There is a missing string in the types (or they are outdated in v1.15.1):
When logging route.request().resourceType() into console, I noticed there is a "images" resource type. So you can easily intercept any images including "images" to your check.
For instance you could do like this:
await page.route('**/*', route => {
return route.request().resourceType().match(/(image)s?/) ?
route.abort() : route.continue();
});

nuxtjs middleware rest API raw data requests

I have build nuxtjs example with built in rest API requests with middleware technique. In index.js of my middleware section I put some code :
export default {
handler(req, res) {
res.write('Everything ok!')
console.log(req);
console.log(res);
res.end()
},
path: '/test15'
}
When I call http://ip:port/test15/?cmd=somecmd&param=testparam
In console.log I get params data in log, everything nice. No matter which method used, post or get, it also fixed in log.
The problem is when I try to send raw data (ex json) in request body or form data. I can`t see them in any log output.
So question is, is it possible to send some data in such requests via middleware ?
Thanks!
middleware in nuxt is a sandwich for internal routes aka client side. For your question serverMiddleware is the answer that work on the server side. You can checkout more here
Quick example:
In your nuxt.config.js file add like below
serverMiddleware: [
{ path: '/api/subscribe', handler: '~/api/subscribe' }
],
Then create an api folder you can create subscribe.js file to add relative api route.
import express from 'express'
const app = express()
app.get('/subscribe', async (req, res) => {
res.send('love to the world');
})
export default {
path: '/api',
handler: app
}

Nuxt Apollo with dynamic headers for a session based authentication

Apollo is not storing the header from the query dynamically.
pages/index.vue
methods: {
fetchCars() {
const token = Cookies.get('XSRF-TOKEN')
console.log(token) // 🟢 Token is shown in console
this.$apollo.query({
query: gql`
query {
cars {
uuid
name
}
}
`,
headers: {
'X-XSRF-TOKEN': token, // â­• Fetch without header
},
})
},
},
Is there a way to set the header value new for every Apollo request?
I have a separate Frontend and Backend. For the Frontend I am using Nuxt.js with Apollo. I want to have a session based communication with my server. For this reason I need to send the CSRF-Token with every Request.
Now the problem: On the first load of the page there is no Cookie set on the browser. I do a GET-Request on every initialization of my Nuxt application.
plugins/csrf.js
fetch('http://127.0.0.1:8000/api/csrf-cookie', {
credentials: 'include',
})
Now I have a valid Cookie set on my side and want to communicate with the GraphQL Server but my header is not set dynamically in the query. Does anyone know how I can solve this?
My Laravel Backend is throwing now a 419 Token Mismatch Exception because I did not send a CSRF-Token with my request.
Link to the repository: https://github.com/SuddenlyRust/session-based-auth
[SOLVED] Working solution: https://github.com/SuddenlyRust/session-based-auth/commit/de8fb9c18b00e58655f154f8d0c95a677d9b685b Thanks to the help of kofh in the Nuxt Apollo discord channel 🎉
In order to accomplish this, we need to access the code that gets run every time a fetch happens. This code lives inside your Apollo client's HttpLink. While the #nuxtjs/apollo module gives us many options, we can't quite configure this at such a high level.
Step 1: Creating a client plugin
As noted in the setup section of the Apollo module's docs, we can supply a path to a plugin that will define a clientConfig:
// nuxt.config.js
{
apollo: {
clientConfigs: {
default: '~/plugins/apollo-client.js'
}
}
}
This plugin should export a function which receives the nuxt context. It should return the configuration to be passed to the vue-cli-plugin-apollo's createApolloClient utility. You don't need to worry about that file, but it is how #nuxtjs/apollo creates the client internally.
Step 2: Creating the custom httpLink
In createApolloClient's options, we see we can disable defaultHttpLink and instead supply our own link. link needs to be the output of Apollo's official createHttpLink utility, docs for which can be found here. The option we're most interested in is the fetch option which as the docs state, is
a fetch compatible API for making a request
This boils down to meaning a function that takes uri and options parameters and returns a Promise that represents the network interaction.
Step 3: Creating the custom fetch method
As stated above, we need a function that takes uri and options and returns a promise. This function will be a simple passthrough to the standard fetch method (you may need to add isomorphic-fetch to your dependencies and import it here depending on your setup).
We'll extract your cookie the same as you did in your question, and then set it as a header. The fetch function should look like this:
(uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
Putting it all together
Ultimately, your ~/plugins/apollo-client.js file should look something like this:
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-fetch'
export default function(context) {
return {
defaultHttpLink: false,
link: createHttpLink({
uri: '/graphql',
credentials: 'include',
fetch: (uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
})
}
}

Shopify GraphQL using fetch API, returns empty json, no errors

Trying to just fetch the name of my store in a React component using the Fetch API and GraphQL endpoint of Shopify.
I created a Shopify store, gave permissions to the Storefront API and crafted this in my componentDidMount() section of my react component.
let query = '{ shop { name } }';
console.log(JSON.stringify(query));
fetch('https://myStoreName.myshopify.com/api/graphql', {
method: "POST",
headers: {
"Content-Type": "application/graphql",
"X-Shopify-Storefront-Access-Token": "<My API Key>"
},
body: JSON.stringify(query),
})
.then(function(myJson) {
console.log('fetched');
console.log(JSON.stringify(myJson));
});
My console log output:
"{ shop { name } }"
App.js:21 fetched
App.js:22 {}
I'm not even getting an error, makes me think it's going through possibly?
But can't find my shop's name in this query?
I think overall I don't know best practices to craft a GraphQL query in Javascript.
Do I make a large string or just a normal, JSON to represent it?
*Also I'm trying not to use a graphQL client library at the moment, and just to use fetch API.
You can't read the response the fetch call resolves to directly like that. Instead, you should call whatever method is appropriate for the mime type you're fetching. From the Mozilla docs:
Once a Response is retrieved, there are a number of methods available to define what the body content is and how it should be handled.
For JSON, you call the json method. You can see more examples here. That means your code should look more like this:
fetch(...)
.then(res => res.json())
.then(console.log)
Also, please bear in mind that you don't need to stringify your query. You should probably use the application/json content type (which is standard, I believe) and wrap your query inside an object like this.
body: { query },
Then if you have variables, these can be included in the same object:
body: { query, variables }

Resources