Proxying Backend Requests In NextJS - javascript

I was trying to proxy requests to my backend. Going through docs, I found out that we can add a rewrite() function in config,
module.exports = {
basePath: "",
distDir: "build",
trailingSlash: true,
images: {
domains: ["localhost"],
},
async rewrites() {
return {
beforeFiles: [
{
source: "/api/:path*",
destination: "http://localhost:3001/todos/:path*",
},
],
};
},
};
I tried this but it fails .It fires two request to API for one each, here the first request says 308 permanent redirect, and the second request says 404. And thats it, it does not requests the api.
Can someone help me?

Related

Issues in testing REST API using Cypress in corporate env

I am working in a corporate environment. I need to test certain APIs using Cypress. The major challenge I have is I need to call APIs which require Client Certificates to be passed. However, the Client Certificates are not being detected by Cypress.
I followed the steps laid out to for configuring proxy as explained in: https://docs.cypress.io/guides/references/proxy-configuration#Set-a-proxy-on-Linux-or-macOS
I am able to test the UI using Cypress in our corporate env.
However, when testing with REST APIs, i followed the steps here to capture the ClientCertificates as our API use certs for auth.
https://docs.cypress.io/guides/references/client-certificates
But I get a timeout error:
`CypressError
cy.request() failed trying to load:
https://apiendpoint1.com:1234/v1/resourceName
We attempted to make an http request to this URL but the request failed without a response.
We received this error at the network level:
Error: Error establishing proxy connection. Response from server was: HTTP/1.1 503 Service Unavailable
Cache-Control: no-cache
Pragma: no-cache
X-XSS-Protection: 1
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 935`
CYPRESS.JSON
{ "viewportHeight":1080, "viewportWidth":1920, "testFiles": "**/*.{feature,features,js}", "defaultCommandTimeout": 60000, "responseTimeout":120000, "supportFile": "cypress/support/index.js", "reporter":"mochawesome", "reporterOptions": { "reportDir": "cypress/results", "overwrite": false, "html": true, "json": false }, "pageLoadTimeout": 120000, "env": { "testEnv": "qa", "apiendpoints":{ "apiendpoint1": "https://apiendpoint1.com:1234", "apiendpoint2": "https://apiendpoint2.com:1234" } },"clientCertificates": [ { "url": "https://apiendpoint1.com:1234", "ca": [], "certs": [ { "pfx": "cypress/certs/certs.jks", "passphrase": "cypress/certs/pass_phrase.txt" } ] }, { "url": "https://apiendpoint2.com:1234", "ca": [], "certs": [ { "pfx": "cypress/certs/certs.jks", "passphrase": "cypress/certs/pass_phrase.txt" } ] } ] }
SPEC.JS
describe("SampleTest", () => {
it('gives a response matching a fixture object', () => {
let requestBody = "{ 'name':'nameValue','address':'addressVal'}";
cy.request({
method: 'POST',
url: Cypress.env("apiendpoints").apiendpoint1 + "v1/resourceName",
body: requestBody
})
.then((response) => {
expect(response.body).to.have.property('code', 200);
})
})
})
Environment Variables:
HTTPS_PROXY=http://corporateproxy.com:443/
HTTP_PROXY=http://corporateproxy..com:80/
NODE_EXTRA_CA_CERTS=C:\Users\usrname.dotfiles\bundle.crt
NODE_HOME=C:\Program Files\nodejs
NODE_TLS_REJECT_UNAUTHORIZED=0
NO_PROXY=*.apiendpoint1.com, *.apiendpoint2.com

How to use proxy with vite (vue frontend) and django rest framework

So, you know when you access a view with django rest api on the browser, you get an html page, and when you send something like an ajax request, you get the json? I'm trying to figure out how to mess with the proxy setting for vite, but I can't find a single decent documentation around it. I want to redirect '/' to 'http://localhost:8000/api', but there's really weird behavior going on.
If I have a route on localhost:8000/api, I can do:
//vite.config.js
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
//Focus here
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => { console.log(path); return path.replace('/^\/api/', '') }
}
}
}
})
//todo-component.vue
export default {
data() {
return {
todos: []
}
},
components: {
TodoElement
},
beforeCreate() {
//Focus here as well
this.axios.get('/api').then((response) => {
this.todos = response.data
})
.catch((e) => {
console.error(e)
})
}
}
This will return the json response as expected. However, if I try to make it so that '/' routes to 'localhost:8000/api/', like this:
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
//change here
'/': {
target: 'http://localhost:8000/api',
changeOrigin: true,
rewrite: (path) => { console.log(path); return path.replace('/^\/api/', '') }
}
}
}
})
import TodoElement from "./todo-element.vue"
export default {
data() {
return {
todos: []
}
},
components: {
TodoElement
},
beforeCreate() {
//change here
this.axios.get('/').then((response) => {
this.todos = response.data
})
.catch((e) => {
console.error(e)
})
}
}
It just spews out the html version of the api view, but with no styling, with a bunch of errors
No idea what to do. If someone could explain how this proxy works, i'd really love it. I don't want to keep writing "api/", and it'd be really valuable if I can manage to understand how this works.
You are a bit confusing things and I will try to show you why.
If you redirect root path / to /api, every request sent to your app running at http://localhost:3000 will be forwarded to http://localhost:8000/api. It mean that you will not be able to serve anything from the running app, but you will get an answer from the configured endpoint (localhost:8000/api) for every request.
To understand easily what is going on, keep in mind that this vite config option (server.proxy) act like a reverse proxy. As example, I take the favicon.ico resource of your app.
With your current configuration, when from your browser you try to access your app, the /favicon.ico (and all other resources) is then loaded from http://localhost:8000/api/favicon.ico and not anymore from your app running at http://localhost:3000/favicon.ico.
This explain all the errors in the console. Again, for example, /static/rest_framework is loaded from http://localhost:8000/api/ and not http://localhost:3000/.
The documentation is quite clear, it's just a matter of understanding what a http-proxy is. To get more information you can head to https://github.com/http-party/node-http-proxy#core-concept

MS graph API: 400 AuthenticationError with "/me/onlineMeetings" request

I am trying to create an online meeting and recover its URL like explained here in the docs, but when the request is run I get this error:
{
"statusCode": 400,
"code": "AuthenticationError",
"message": "Error authenticating with resource",
"requestId": "652ea3be-6a97-47e8-bfc6-3d7d1d51d425",
"date": "2020-09-01T12:53:41.000Z",
"body": "{
"code":"AuthenticationError",
"message":"Error authenticating with resource",
"innerError":{
"date":"2020-09-01T13:53:41",
"request-id":"652ea3be-6a97-47e8-bfc6-3d7d1d51d425"
}
}"
}
I tried also the get started projet for JS and it's working fine so I can't spot the problem.
here is what I used:
const msalConfig = {
auth: {
clientId: 'my_app_id',
redirectUri: 'http://localhost:8080'
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
forceRefresh: false
}
};
const loginRequest = { scopes: [
'openid',
'profile',
'user.read',
'calendars.read',
'User.Read.All',
'User.Export.All'
]
}
const options = new MicrosoftGraph.MSALAuthenticationProviderOptions([
'user.read',
'calendars.read',
'OnlineMeetings.ReadWrite'
]);
const onlineMeeting = {
startDateTime:"2020-09-01T16:00:34.2444915-07:00",
endDateTime:"2020-09-01T16:30:34.2464912-07:00",
subject:"test meeting"
};
const authProvider = new MicrosoftGraph.ImplicitMSALAuthenticationProvider(msalClient, options);
// Initialize the Graph client
const graphClient = MicrosoftGraph.Client.initWithMiddleware({authProvider});
// then I call this inside an async function
let events = await graphClient.api('/users/my_UserPrincipalName/onlineMeetings').post(onlineMeeting);
//let events = await graphClient.api('/me/onlineMeetings').post(onlineMeeting);
// I tried with both calls and none of them worked
and here are the permissions on azure active directory:
So any ideas on how to solve this ?
thanks
You didn't provide a correct access token.
Since Create onlineMeeting only supports Delegated (work or school account) permission type, you need to get the access token with Auth code flow or Implicit flow.
The started project for JS is using Implicit flow. So you can use Implicit flow to get the access token.
Here is the example in Postman:
The Auth URL above is https://login.microsoftonline.com/{your tenant}/oauth2/v2.0/authorize.
I figured out how to make it work in my code:
let's call my user, which I used all this time, user "A", all I did is that I simply created another user "B" in Azure Active Directory and then logging in with this new user "B" in the login screen instead of the admin user "A" that I used before..... and now it's working.
But this does not explain the issue, so if anyone can explain the difference or why it didn't work with the first account, that would be very helpful.

NextJs :pid routes

Does anybody know what is the exportPathMap: (next.config.js) for NextJS of a path that has a :pid?
My expotPathMap
exportPathMap: async (defaultPathMap) => {
return {
'/': { page: '/', query: {} },
'/login': { page: '/login', query: { verifySuccess: null } },
'/signup': { page: '/signup', query: {} },
'/search': { page: '/search', query: { s: '', category: '' } },
'/messages': { page: '/messages', query: { t: '' } },
'/messages/:pid': { page: '/messages/:pid', query: { t: '' } },
Issue is that I was tasked to create a page that would look like
/messages/925255252
instead of a page that uses a query param like /message?id=9252552252&t=foo
Now when building & exporting I am getting this error
Cannot find module for page: /messages/:pid
The files.
pages > messages > index.js (/messages), [pid].js (messages/:id)
PS.
Not using SSR, rendering is client sided!
PPS.
All is fine on localhost, needs to work in production.
What you are trying to achieve is not possible, from the spectrum chat of next.js :
You have to return a mapping of every possible route, dynamic matching
wouldn't have any effect even if we did support it, how would you know
what /show/:id is going to be when exporting? We have to know exactly
what is going to be exported at export time
So you have to generate all possibile pages (in your case you need all possible messages ids), example fetching your database.
Or switch to SSR and handle your requests server side.

Changing credentials to a proxy server on the fly

I'm developing an extension for chrome. The extension allows to pick any proxy server from a list, each proxy is required authorization. There is an issue when a user would like to connect to the same proxy server twice but with different credentials for example if a user was successfully logged in the first time the chrome remembers it and when the user would try to connect with other credentials the chrome would use credentials that were inputted in the first login.
var authCredentials = {
username: 'Jack',
password: 'PassForJack'
}
var auth = function () {
return {
authCredentials
};
};
chrome.webRequest.onAuthRequired.addListener(auth, {
urls: ["<all_urls>"]
}, ["blocking"]);
// set a new proxy server for the first login
chrome.proxy.settings.set({
value: {
mode: 'fixed_servers',
rules: {
singleProxy: {
host: 'some-proxy-server.com',
port: 8000
}
}
},
scope: 'regular'
});
// change credentails
authCredentials = {
username: 'Bob',
password: 'PassForBob'
};
// remove proxy configuration
chrome.proxy.settings.set({
value: {
mode: 'direct'
},
scope: 'regular'
});
// remove onAuthListener
chrome.webRequest.onAuthRequired.removeListener(auth)
chrome.webRequest.onAuthRequired.hasListener(auth) // returns false
chrome.webRequest.onAuthRequired.addListener(auth, {
urls: ["<all_urls>"]
}, ["blocking"]);
// lets re connect
chrome.proxy.settings.set({
value: {
mode: 'fixed_servers',
rules: {
singleProxy: {
host: 'some-proxy-server.com',
port: 8000
}
}
},
scope: 'regular'
});
// that doesn't help the user would be logged as "Jack" but has to be as "Bob"
There are multiple possibilities here since the question is not very clear. I would suggest to walk through documentation for the chrome.webRequest first. But My question would be why don't you use interceptor method to check for server-credential pair ? There's a good article about adding interceptor in the background.js script of your extension which suggests to use the beforeRequest hook.

Categories

Resources