What is [Symbol(kHeaders)] and how do I parse it as headers - javascript

I am having trouble parsing the header retrieved from graphql's context, what I would like to do is to basically forward the headers from the request into the response
My gateway:
GraphQLModule.forRootAsync<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
inject: [ConfigService],
useFactory: async(configService: ConfigService) => ({
server: {
introspection: true,
playground: true,
cache: 'bounded'
},
gateway: {
buildService: (url) => new CustomDataSource(url),
supergraphSdl: ...
}
})
})
My CustomDataSource which should forward headers:
export class CustomDataSource extends RemoteGraphQLDataSource {
constructor(config: any) {
super(config);
this.fetcher = fetcher.defaults({
maxSockets: Infinity,
strictSSL: false,
retry: false,
})
}
willSendRequest({context, request }) {
console.log('context', context.req); // <---- here
request.http?.headers.set('authorization', context.req.authorization);
}
}
My issue now is that the context.req.headers do not exist when it should and logging it out gives me headers in a different name as kHeaders instead which I am unsure of how to parse this.
context.req:
{
...,
...,
[Symbol(kHeaders)]: {
authorization: 'abcdefg'
}
}
I tried something like context.req['Symbol(kHeaders)'] which returns me cannot read properties, would like to know why is my headers returned this way and how do I parse this

Related

cypress.origin throws error: (uncaught exception)Error: on only accepts instances of Function

I am using Cypress with Cucumber.
I am trying to test cross origin login but the origin method keeps on throwing error:
Code:
Given(/^the user login to the Test Page$/, function () {
cy.visit("https://example-originalURL");
cy.get("button").contains("Login").click();
const credentials = {
username: "hello",
password: "user",
};
cy.origin("https://example-newURL", { args: credentials }, ({ username, password }) => {
cy.get("#email", { timeout: 20000 }).type(username);
cy.get("#password").type(password, { log: false });
cy.get("button").contains("Login").click();
});
});
Cypress.config.js
module.exports = defineConfig({
projectId: "t7unhv",
e2e: {
setupNodeEvents(on, config) {
on("file:preprocessor", cucumber());
on('task', {
log(message) {
console.log(message +'\n\n');
return null;
},
});
},
specPattern: "./cypress/e2e/features/*.feature",
chromeWebSecurity: false,
experimentalSessionAndOrigin: true,
defaultCommandTimeout: 15000,
env: {
devCentralUrl: "https://***.dev.***.com.au/login",
testCentralUrl:
"https://***.test.***.com.au/login",
test***: "http://***.test.***.com.au",
dev***: "http://***.dev.***.com.au",
uat***: "https://***.uat.***.com.au",
dataSource: "",
environs: "test",
},
retries: {
runMode: 0,
},
pageLoadTimeout: 15000,
reporter: "mochawesome",
reporterOptions: {
reporterEnabled: "mochawesome",
mochawesomeReporterOptions: {
reportDir: "cypress/reports/mocha",
quite: true,
charts: true,
overwrite: false,
html: false,
json: true,
},
},
},
});
Error:
The following error originated from your test code, not from Cypress.
> on only accepts instances of Function
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
I have tried multiple syntax changes like not passing the credentials as optional argument to cy.origin.
If someone can provide a quick help, that will be great.
If the problem is in the test code, it is likely to be that newURL is undefined. The error message suggests the problem is in the app, but that might be a red herring.
Try just adding a fixed string for the cy.origin() key,
cy.origin('login', { args: credentials }, ({ username, password }) => {
...
})

Get token from URL and send to post api with Axios Vuejs

Hi i need to take token from URL http://192.168.178.25:8080/register?token=eyJhbGciOiJIUzI...
and send a Post request on API for confermation account
I have tried this but on backend i've receive SyntaxError!
Someone can help me?
<script>
import axios from 'axios'
export default {
name: 'Register',
data() {
return {
confirmation : false,
somethingWrong: false
}
},
created: function() {
axios.post('/api/users/validateRegister', null,{
params: {
registerToken: this.$route.query.token,
state: this.$route.query.state
}
})
.then((res) => {
console.log(res)
this.confirmation = true
})
.catch((err) => {
console.log(err)
this.somethingWrong = true
})
}
}
</script>
Your server is expecting JSON but you are sending something else.
Try running this in your browser console (devtools): JSON.parse('asdasd').
How you are sending it right now:
axios.post('/api/users/validateRegister', null,{
params: {
registerToken: this.$route.query.token,
state: this.$route.query.state
}
})
Will send a request that looks like:
/api/users/validateRegister?registerToken=<token>&state=<state>
To do a POST request with body according to docs, you do:
axios.post(url[, data[, config]])
Which in your case means, assuming you need registerToken and state as part of body and not query parameters:
axios.post('/api/users/validateRegister',{
registerToken: this.$route.query.token,
state: this.$route.query.state
})
Notice how there's no null in the 2nd param and no params: {}
You can also according to docs do the following syntax:
axios({
method: 'post'
url: '/api/users/validateRegister',
data: {
registerToken: this.$route.query.token,
state: this.$route.query.state
}
})
It looks like your server is throwing an error when trying to parse the body.
From your axios request, you're passing parameters instead of a body - you can see this by looking at the URL in the POST error on the right-hand side of your screenshot.
Instead, send the payload in the body like this;
axios.post('/api/users/validateRegister',
{
registerToken: this.$route.query.token,
state: this.$route.query.state
})
As you haven't provided any of the server-side code there may be something else going on we can't see.

Why Nuxt making multiple request for the "user" endpoint?

There is an Express server and a Nuxt client. Nuxt version is 2.15.7.
Entire auth configuration:
// nuxt.config.js
auth: {
plugins: [
{
src: '~/plugins/axios',
ssr: true
},
{
src: '~/plugins/auth'
}
],
cookie: {
prefix: 'auth.',
options: {
path: '/',
secure: process.env.NODE_ENV === 'production' ? true : false
}
},
localStorage: {
prefix: 'auth.'
},
vuex: {
namespace: 'auth'
},
strategies: {
local: {
scheme: 'refresh',
token: {
property: 'accessToken',
maxAge: 900,
global: true,
name: 'Authorization',
type: 'Bearer'
},
refreshToken: {
property: 'refreshToken',
data: 'refreshToken',
maxAge: 5184000
},
user: {
property: 'user',
autoFetch: false
},
endpoints: {
login: {
url: '/user/sign_in',
method: 'post'
},
logout: {
url: '/user/sign_out',
method: 'delete'
},
refresh: {
url: '/user/refresh',
method: 'get'
},
user: {
url: '/user/profile',
method: 'get'
}
}
}
},
redirect: {
login: '/auth/sign_in',
logout: '/',
callback: '/auth/sign_in',
home: '/'
}
}
When I refresh the page in the browser, I see this in the browser log:
This message comes from here:
// plugins/axios.ts
import { AxiosRequestConfig } from 'axios'
export default function ({ $axios, }: any) {
$axios.onRequest((config: AxiosRequestConfig) => {
console.log('Making request to ' + config.url)
})
}
There are also two requests in the server logs. But in the first request I can get, for example, cookies, and in the second one comes this:
// console.log(req.cookies)
[Object: null prototype] {}
Can you please tell me why there are two requests?
The problem was caused by the back end returning this after sign in:
{
"is": 1
}
And should return this:
{
"user": {
"is": 1
}
}
😬
After I added the "user" object, nuxt auth accepted the information and started working correctly.

How to set `You and moderator can reply` in bot when posting proactive message to channels?

I am currently developing a bot that posts proactive message to channels. My client wants me to set No reply or You and moderator can reply on the message that posted from the bot proactively. 
What I tried so far:
// post message to channels
const credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
const client = new ConnectorClient(credentials, { baseUri: serviceUrl });
const message = MessageFactory.text(inMessage);
let approveResult = false;
let MessageActivityId = "";
const conversationParams = {
isGroup: true,
bot: {
id: process.env.MicrosoftAppId,
name: process.env.BotName
},
conversationType: 'channel',
channelData: {
channel: {
id: teamsChannelId
}
},
activity: message
};
const msRes = await client.conversations.createConversation(conversationParams).catch(e => console.log(e));
I tried to post the message first, and immediately update the activity and set the type as ActivityTypes.EndOfConversation. However, it doesn't work at all.
const tmpResult = await client.conversations.updateActivity(teamsChannelId, msRes.activityId, {type: ActivityTypes.EndOfConversation})
Error form above updateActivity code: 
RestError: Unknown activity type
at ...(skipped for paths)
{
code: 'BadArgument',
statusCode: 400,
request: WebResource {
streamResponseBody: false,
url: 'https://{service_url}/{channel_id}/activities/{messageActivityId}',
method: 'PUT',
headers: HttpHeaders {
_headersMap: [Object]
},
body: '{"type":"endOfConversation"}',
query: undefined,
formData: undefined,
withCredentials: false,
abortSignal: undefined,
timeout: 0,
onUploadProgress: undefined,
onDownloadProgress: undefined,
proxySettings: undefined,
keepAlive: undefined,
agentSettings: undefined,
operationSpec: {
httpMethod: 'PUT',
path: 'v3/conversations/{conversationId}/activities/{activityId}',
urlParameters: [Array],
requestBody: [Object],
responses: [Object],
serializer: [Serializer]
}
},
response: {
body: '{"error":{"code":"BadArgument","message":"Unknown activity type"}}',
headers: HttpHeaders {
_headersMap: [Object]
},
status: 400
},
body: {
error: {
code: 'BadArgument',
message: 'Unknown activity type'
}
}
}
Is there any method that allows me to do so? Thanks.
It would be better if I could only disable the reply function in Channels from bot programmatically.
Update on 2021-06-28:
Simulation of expected behavior on UI:
Simulation of actual behavior on UI:
I've not actually tested this property myself, but it seems like it should handle what you need: In the Teams app manifest, there is a "NotificationOnly" setting on the bot, which means it should not allow users to converse with it (i.e. "reply"). See more at https://learn.microsoft.com/en-us/microsoftteams/platform/resources/bot-v3/bots-notification-only

How to add form-data to Laravel Echo request?

I'm trying to send some data with Laravel Echo request
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'somekey',
wsHost: '127.0.0.1',
wsPort: 6001,
encrypted: false,
disableStats: true,
forceTLS: false,
authEndpoint: 'http://127.0.0.1:8000/broadcasting/auth',
'form-data': { // I tried data, dataForm, dataform
someData: '123', // this doesn't seem to work
},
});
I've seen how to add custom headers to the request
auth: {
headers: {
token: '123'
}
}
Is there any way to add form-data in a similar way?
Edit
When I inspect the network requests in the DevTools, I can see that there are two formData properties sent by the Echo to the server. So I thought there must be a way to attach additional properties into the existing formData object
Is there any way to add form-data in a similar way?
The simple answer is - NO
Laravel Echo doesn't have the functionality to achieve that within the parameter set.
The reason we can see the Form Data object in the Dev Tools requests, is because pusher-js is adding them before making the request to the server. To achieve that, we would have to manipulate the pusher API before the request is executed, but this goes off the original topic of this thread.
So if you want to send the data to the server, the easiest would be adding custom headers as pointed in the original question.
...
auth: {
headers: {
token: '123'
}
}
...
Edit 1
I'm really not sure if this would actually work but can you try this when you can
class LaravelEcho extends Echo {
constructor(options) {
super(options);
this.setformData();
}
setformData(formData = this.options.formData) {
if (formData) {
let path =
"?" +
Object.entries(formData)
.map((ch) => ch.join("="))
.join("&");
this.options.authEndpoint += path;
this.connector.options = this.options;
// since you are using pusher
if (this.connector.pusher) {
this.connector.pusher.options = this.options;
}
// maybe also for socket.io too?
else if (this.connector.socket) {
this.connector.socket.options = this.options;
}
}
}
}
let myEcho = new LaravelEcho({
broadcaster: "pusher",
key: "somekey",
wsHost: "127.0.0.1",
wsPort: 6001,
encrypted: false,
disableStats: true,
forceTLS: false,
authEndpoint: "http://127.0.0.1:8000/broadcasting/auth",
formData: {
foo: "bar",
username: "username",
password: "password",
},
});
console.log(myEcho);
I know this is really not the way you want. I've tried to make it as #Islam said on the comment and I'm really wondering if this is gonna work like this if we just override options after creation :)
Old
I was looking into this. here I saw that there is a headers option as following:
private _defaultOptions: any = {
auth: {
headers: {},
},
authEndpoint: '/broadcasting/auth',
broadcaster: 'pusher',
csrfToken: null,
host: null,
key: null,
namespace: 'App.Events',
};
This is Connecter's default options and inside it's constructor it's also setting an auth header for csrfToken here
So I'm guessing while you are creating your Laravel/Echo you might do,
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'somekey',
wsHost: '127.0.0.1',
wsPort: 6001,
encrypted: false,
disableStats: true,
forceTLS: false,
authEndpoint: 'http://127.0.0.1:8000/broadcasting/auth',
auth: {
headers: {
'X-CSRF-TOKEN': 'your-csrf-token'
'your-header': 'with-value'
}
}
});
Hope this would work for you. Please do let me know! :)
By the way I don't have a test environment so i never tested it..

Categories

Resources