How does redirecting from a post method to get method work? - express

The server doesn't recognize any get request except for the post method after executing some queries in the mongodb.
The express middleware takes the post method and after interacting with the database and using the res.redirect() to get to other get methods, the server doesn't recognize the request at all. I tried using res.all(). This showed that the request was seen but no action was taken.
var express = require('express');
var router = express.Router();
var Product = require('../models/product');
router.get('/', function(req, res, next) {`//homepage
res.render("index");
}
router.post('/add',function(req,res next){
//Product model
var prod = new Product({
//data here
});
prod.save(function(err,res2){
if(err){
console.log(err);
return res.redirect('/error');
}
else{
mongoose.disconnect();
console.log("Complete1");
return res.redirect('/');
console.log ("Complete2);
}
});
}
After I get to the post method it should redirect to the homepage

The problem may not be with the backend, but with the frontend. If you are using AJAX to send your POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the reques

Related

Set cookie after fetch request response from auth server

I just started learnign about the express library, im developing an app that access restricted info about a user using an Eve Online API, to do this the user is redirected to an authentication page to get an access and refresh token.
Everything works fine until I try to pull the 'refresh_token' from the response and set a cookie with it.
The error:
(node:20600) UnhandledPromiseRejectionWarning: TypeError: res.cookie is not a function
My code:
const url = 'https://login.eveonline.com/v2/oauth/token';
const options = {
'method':'POST',
headers:
{
'authorization':'Basic '+ process.env.ENV_PASS,
'Content-Type':'application/x-www-form-urlencoded',
'host':'login.eveonline.com'
},
body:''
}
function send_get_request(req, res){
options.body =`grant_type=authorization_code&code=${req.query.code}`
fetch(url,options,{credentials:'include'})
.then(handle_stream)
.then(handle_json)
.then(set_cookie)
.then(redirect_home)
}
function handle_stream(res){
return res.json() //handless data stream, returns responce
}
function handle_json(res){
return res.refresh_token
}
function set_cookie(res){
return res.cookie('refresh_token','hello')
}
function redirect_home(res){
res.redirect('http://localhost:3000/home')
}
router.get('/',send_get_request)
I tried breaking the .then() block but still res.cookie doesn't exits. Also tried using credentials but it doesn't work.
Your code contains two variables res: One stands for the response that your middleware sends back to the client, the other stands for the response you are receiving from the fetch operation. Only the handle_stream function operates on the latter, whereas set_cookie and redirect_home operate on the former.
The last three function are also synchronous and need not be chained with .then. The are invoked synchronously in a function that takes as parameter the json which handle_stream produces asynchronously.
function send_get_request(req, res){
options.body =`grant_type=authorization_code&code=${req.query.code}`;
fetch(url,options,{credentials:'include'})
.then(handle_stream)
.then(function(json) {
var refresh_token = handle_json(json);
set_cookie(res, refresh_token);
redirect_home(res);
});
}
It is all perhaps easier to understand with the async-await syntax:
async function send_get_request(req, res){
options.body =`grant_type=authorization_code&code=${req.query.code}`;
var response = await fetch(url,options,{credentials:'include'});
var json = await handle_stream(response);
var refresh_token = handle_json(json);
set_cookie(res, refresh_token);
redirect_home(res);
}

Why I am getting POST 404 when Calendly is posting data to my endpoint

I created Calendly Webhook Subscription by following their instructions. My backend is written in NodeJS + Express. I am trying to implement Calendly webhook while I got the trial period. I am exposing the endpoint /webhooks/calendly/calendlyWebhook on localhost:8080 and I am doing it through ngrok, because Calendly supports only https protocol. I see in my logs Calendly sending a post request to the endpoint, but I am seeing it being 404: POST /webhooks/calendly/calendlyWebhook 404.
Here is my webhook file called calendlyWebhook.js
const { Router } = require('express');
const calendlyWebhookRouter = Router();
calendlyWebhookRouter.post('/calendlyWebhook', async (req, res) => {
console.log("Hello from calendly webhook ✅")
return res.statusCode(200).send('Ok')
})
module.exports = {
calendlyWebhookRouter,
};
And here is my index.js file where I initialize the router
...
...
const {calendlyWebhookRouter} = require('./webhooks/calendlyWebhook');
app.use('/webhooks/calendly/calendlyWebhook', calendlyWebhookRouter);
...
What exactly I am doing wrong?
The webhook route contains calendlyWebhook twice (once in the app.use path and once in the calendlyWebhookRouter path). As a result, calendlyWebhookRouter will only be called when a POST request is sent to /webhooks/calendly/calendlyWebhook/calendlyWebhook.
Removing calendlyWebhook from the app.use route path should resolve the issue:
app.use('/webhooks/calendly', calendlyWebhookRouter);

Shopify API Cross Domain Ajax Request

I am using the below code to get the customer details from shopify. I have redirected my domain to the other domain from the shopify admin.
function setEmailWithLoggedInUser(callback) {
$.ajax({
url: 'https://new-website-shopify.myshopify.com/admin/customers/'+__st.cid+'.json',
crossDomain: true,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic XXXXXXXXXXXX")
}, success: function(data){
console.log(data);
if(callback)
callback();
}
})
I have done a lot of work around but unable to find the solution.
I am getting this error:
Failed to load resource: the server responded with a status of 404
(Not Found)
XMLHttpRequest cannot load
https://new-website-shopify.myshopify.com/admin/customers/7094124372.json.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://www.beirutshopping.com' is therefore not
allowed access. The response had HTTP status code 404.
I will save you some headaches with this answer. You cannot call /admin from the front-end of a store, as that exposes your access token to the public. Instead, if you want to access the API from the front-end, use the App Proxy pattern, allowing you to securely make Ajax calls to accomplish your goals.
As it is, you are almost certain to fail, and any success you hack into existence will quickly expose your shop to horrors. Like being replaced with sad pandas, or otherwise being reckd.
var cors = require('cors');
router.use(cors({
origin: '*'
}));
//var config = require('../config/config.json');
//testing /* GET home page. */
router.get('/', function (req, res, next) {
res.setHeader("Content-Type", "application/liquid");
res.setHeader("Access-Control-Allow-Origin", "*");
res.render('index', {
title: 'Store Locator'
});
});

Where do you place NPM's request code?

I want to use the request module in my express app, but I am not sure where the actual requests code goes.
Usage:
When a user loads a page, make a GET request and populate the page with data.
When a users clicks on a item from a table, make a GET request.
When a user fills out a form, POST.
I tried searching for answers but it seems to be implied that the developer knows where to place the code.
Example of a code snippet using request that I am unsure where to place in the express app:
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
})
I am guessing that I should not place the code in the server.js file especially if I am going to be making many different calls, but that's what it looks like others are doing on StackOverflow.
Does the request belong in a model?
If you are doing this in response to a user interaction, like clicking on something you can just do it from the route handler. Below, I just return the results to the client, or I pass an error to the next handler in the chain.
var request = require('request');
var express = require('express');
var app = express();
app.get('/click', function(req, res, next){
request('http://www.google.com', function (error, response, body) {
if (error || response.statusCode != 200)
return next(err);
response.send(body) // return the html to the client
})
});
app.listen(3000);
In bigger apps you might move routes into separate modules.

Using Node JS to proxy http and modify response

I'm trying to write a front end to an API service with Node JS.
I'd like to be able to have a user point their browser at my node server and make a request. The node script would modify the input to the request, call the api service, then modify the output and pass back to the user.
I like the solution here (with Express JS and node-http-proxy) as it passes the cookies and headers directly from the user through my site to the api server.
proxy request in node.js / express
I see how to modify the input to the request, but i can't figure out how to modify the response. Any suggestions?
transformer-proxy could be useful here. I'm the author of this plugin and I'm answering here because I found this page when looking for the same question and wasn't satisfied with harmon as I don't want to manipulate HTML.
Maybe someone else is looking for this and finds it useful.
Harmon is designed to plug into node-http-proxy https://github.com/No9/harmon
It uses trumpet and so is stream based to work around any buffering problems.
It uses an element and attribute selector to enable manipulation of a response.
This can be used to modify output response.
See here: https://github.com/nodejitsu/node-http-proxy/issues/382#issuecomment-14895039
http-proxy-interceptor is a middleware I wrote for this very purpose. It allows you to modify the http response using one or more transform streams. There are tons of stream-based packages available (like trumpet, which harmon uses), and by using streams you can avoid buffering the entire response.
var httpProxy = require('http-proxy');
var modifyResponse = require('http-proxy-response-rewrite');
var proxy = httpProxy.createServer({
target:'target server IP here',
});
proxy.listen(8001);
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes.headers['content-encoding'], function (body) {
if (body && (body.indexOf("<process-order-response>")!= -1)) {
var beforeTag = "</receipt-text>"; //tag after which u can add data to
// response
var beforeTagBody = body.substring(0,(body.indexOf(beforeTag) + beforeTag.length));
var requiredXml = " <ga-loyalty-rewards>\n"+
"<previousBalance>0</previousBalance>\n"+
"<availableBalance>0</availableBalance>\n"+
"<accuruedAmount>0</accuruedAmount>\n"+
"<redeemedAmount>0</redeemedAmount>\n"+
"</ga-loyalty-rewards>";
var afterTagBody = body.substring(body.indexOf(beforeTag)+ beforeTag.length)+
var res = [];
res.push(beforeTagBody, requiredXml, afterTagBody);
console.log(res.join(""));
return res.join("");
}
return body;
});
});