Looking for some assistance with this error.
After hosting my Node.js & Angular project at azure I'm getting that error on POST request:
Http failure response for https://https://green-market.azurewebsites.net/api/auth/login: 405 Method Not Allowed
This is my web.config file:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="iisnode" />
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="Angular Routing" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile"
negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory"
negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
<staticContent>
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
<mimeMap fileExtension="json" mimeType="application/json" />
</staticContent>
</system.webServer>
</configuration>
And this is my app.js file from node.js server:
let originUrl;
if (process.env.PORT) {
global.config = require("./config-prod");
originUrl = "https://green-market.azurewebsites.net";
}
else {
global.config = require("./config-dev");
originUrl = "http://localhost:4200";
}
require("./data-access-layer/dal");
const express = require("express");
const session = require("express-session");
const path = require("path");
const cors = require("cors");
const productsController = require("./controllers/products-controller");
const authController = require("./controllers/auth-controller");
const shoppingCartsController = require("./controllers/shopping-carts-controller");
const ordersController = require("./controllers/orders-controller");
const citiesController = require("./controllers/cities-controller");
const server = express();
const fileUpload = require("express-fileupload");
const { request, response } = require("express");
const { url } = require("inspector");
server.use(fileUpload());
server.use(express.json());
server.use(express.static(path.join(__dirname, "./_front-end")));
server.use(cors({
origin: originUrl,
credentials: true
}));
server.use(session({
name: "OnlineMarketSession",
secret: "itsASecret",
resave: true,
saveUninitialized: false,
}));
server.use("/api/products", productsController);
server.use("/api/shopping-carts", shoppingCartsController);
server.use("/api/orders", ordersController);
server.use("/api/auth", authController);
server.use("/api/cities", citiesController);
// Any other route - return index.html as we are SPA:
server.use("*", (request, response) => {
response.sendFile(path.join(__dirname, "./_front-end/index.html"));
});
const port = process.env.PORT || 3000;
server.listen(port, () => console.log(`Listening on port ${port}`));
Thank you!
Related
I'm fairly new to NodeJS and I'm trying to implement HTTPS request from NodeJS (backend) directly to a middleware api hosted in IISNode with a GoDaddy certificate. I have another repo for my view (frontend) and all the calls to the middleware api through the browser are working with the GoDaddy certificate. The calls work fine with HTTP using Axios. When making the call to the middleware api with HTTPS from the NodeJS backend I'm getting:
Error: self signed certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1058:34)
at TLSSocket.emit (events.js:198:13)
at TLSSocket.EventEmitter.emit (domain.js:448:20)
at TLSSocket._finishInit (_tls_wrap.js:636:8)
It's really weird that the frontend repo communicates with no issue to the middleware via the browser but the NodeJS backend calls will not. I have tried using Axios in the backend with no luck and cert errors. I switched to HTTPS and the GET calls are working, but POST calls give me the error above.
I have read tons of posts and examples regarding self-signed certs but I'm using a cert that is generated from GoDaddy. Here are some code snippets I've tried:
Axios:
const SSLAgent = new https.Agent({
rejectUnauthorized: true,
passphrase: process.env.PASSPHRASE,
pfx: fs.readFileSync(path.join(__dirname, "../../") + process.env.PFX),
ca: fs.readFileSync(path.join(__dirname, "../../") + process.env.CRT_BUNDLE)
});
const fetchData = () => axios.get(`${process.env.MIDDLE_WARE_URL}/something`, {
headers: {
Authorization: `Bearer ${token}`
},
httpsAgent: SSLAgent
});
const uploadData = () => {
const form = new FormData();
form.append("data", fs.createReadStream(dataPath));
return axios.post(`${process.env.MIDDLE_WARE_URL}/data`, form, {
headers: {
...form.getHeaders(),
Authorization: `Bearer ${token}`
},
httpsAgent: SSLAgent
});
};
const fetchItemImage = (ItemID: number) => axios.get(`${process.env.MIDDLE_WARE_URL}/item/${ItemID}/image.png`, {
responseType: "arraybuffer",
headers: {Authorization: `Bearer ${token}`},
httpsAgent: new https.Agent({pfx: fs.readFileSync(path.join(__dirname, "../../") + process.env.PFX), passphrase: process.env.PASSPHRASE}), ca: fs.readFileSync(path.join(__dirname, "../../") + process.env.CRT_BUNDLE)
});
HTTPS:
const SSLAgent = {
rejectUnauthorized: true,
passphrase: process.env.PASSPHRASE,
pfx: fs.readFileSync(path.join(__dirname, "../../") + process.env.PFX),
ca: fs.readFileSync(path.join(__dirname, "../../") + process.env.CRT_BUNDLE)
};
const middleServer = express;
const middle = express.Router();
https.createServer(SSLAgent, middleServer).listen(443);
let data;
const dataOptions = {
headers: {
"Authorization": `Bearer ${token}`
}
};
const fetchData = () => middle.get("/data", (req, res) => {
console.log("The req is: ", req);
if (res.statusCode === 200) {
console.log("The Fetch Data Res: ", res);
data = res;
}
data = [];
});
const uploadStuff = () => {
const form = new FormData();
form.append("Stuff", fs.createReadStream(stuffPath));
const stuffOptions = {
headers: {
...form.getHeaders(),
"Authorization": `Bearer ${token}`
},
form
};
return middle.post("/stuff", (req, res) => {
req.params(stuffOptions);
res.on("data", () => {
console.log("The post response is: ", res);
});
res.on("error", (error) => {
console.log("The post error is: ", error);
});
});
};
Also, here is my IIS web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="iis.js" verb="*" modules="iisnode" />
<add name="iisnode-socketio" path="iis.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="my_middleware">
<match url="/*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTPS_HOST}/{R:1}" />
</rule>
<!-- Don't interfere with requests for logs -->
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
</rule>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="iis.js" logRewrittenUrl="true" />
</rule>
<rule name="SocketIO" patternSyntax="ECMAScript">
<match url="socket.io.+" />
<action type="Rewrite" url="iis.js" />
</rule>
</rules>
</rewrite>
<webSocket enabled="false" />
<iisnode debugHeaderEnabled="true" promoteServerVars="AUTH_USER,AUTH_TYPE,LOGON_USER" />
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="?" verbs="OPTIONS" />
<add accessType="Allow" users="*" roles="" />
</authorization>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
<defaultDocument>
<files>
<add value="iis.js" />
</files>
</defaultDocument>
</system.webServer>
</configuration>
I'm trying to host a simple Nextjs application on Azure WebApp, i have tried to follow several online tutorials to configure it but none managed to help me.
I'm using the SSR configuration of the Nextjs and have only created two components to test it on the Azure hosting.
Right now i'm stuck at the server configuration for Node, i have tried place a web.config file that i saw on an example but it seems that my request isn't event reaching the application server.
This is my web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="app/server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="API">
<match url="^api(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{SCRIPT_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{SCRIPT_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="api/index.php" appendQueryString="true" />
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app/server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app/server.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
This is my server.js
const express = require('express')
const next = require('next')
const nextConfig = require('../next.config')
const port = process.env.PORT || 8080
const dev = process.env.NODE_ENV !== 'production'
const app = next({
dev: dev,
dir: './app',
conf: nextConfig
})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('/home', (req, res) => {
return app.render(req, res, '/home', req.query)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
I'm developping a nodeJS/Angular 6/Express app.
There's only 1 route in express for the "back-end" and many routes for angular.
I have no problems to run that locally but when I try to deploy it on Azure, Angular routes works fine but not back-end routes (which redirect me to the root url).
I think Angular is taking priority on back-end routes.
Here are some files :
server.js :
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const fetch = require('node-fetch');
const publicweb = './dist/forms';
const app = express();
app.use(express.static(publicweb));
app.use('/api/test', (req, res) => {
res.send("test");
});
app.get('*', (req, res) => {
res.sendFile('index.html', { root: publicweb });
});
const port = '1337';
app.listen(port, () => console.log(`API running on localhost:${port}`));
web.config :
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="Express.js URIs">
<match url="api/*" />
<action type="Rewrite" url="server.js" />
</rule>
<rule name="Angular" stopProcessing="true">
<match url="/*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory"
negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
package.json :
"start" : "node src/server.js"
app-routing.module.ts :
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { RetailComponent } from './retail/form/retail.component';
const routes: Routes = [
{
path: '',
redirectTo: '/',
pathMatch: 'full'
},
{
path: 'retail',
component: RetailComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
When I deploy that app on Azure, and I try to access /api/test
My build definition in Azure
Many thanks for your answer!
I think all your get request are mapping to this piece of code
app.get('*', (req, res) => {
enter code here`res.sendFile('index.html', { root: publicweb });
});
that is why you are getting index.html in your queries to your server.
And app.use() is to be used for applying middleware so after middleware work is over the app.get() method gets executed and so you get index.html
I want to run angular 4 univeral in Azure Web. I deployed the code, but I have some troubles with web.config (i think so).
The server.js located in dist folder, so I set path in web.config "dist/server.js", but when server.js runs it gives an error:
ENOENT: no such file or directory, open 'D:\home\site\wwwroot\dist\dist\browser\index.html'
If I remove the "dist" from path it will 404. And if I remove "dist" from
const DIST_FOLDER = join(process.cwd(), 'dist'); in server.js
it will give me an error:
ENOENT: no such file or directory, open 'D:\home\site\wwwroot\browser\index.html'
Or double dist, or no dist at all.
The web.config looks like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="dist/server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^dist/server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="dist/server.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
The server.js code:
const PORT = process.env.PORT || 8080;
const DIST_FOLDER = join(process.cwd(), 'dist');
const app = express();
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
const { AppServerModuleNgFactory } = require('main.server');
app.engine('html', (_, options, callback) => {
const opts = { document: template, url: options.req.url };
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html => callback(null, html));
});
app.set('view engine', 'html');
app.set('views', 'src');
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
app.get('*', (req, res) => {
res.render('index', { req });
});
app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});
I figured out, instead of process.cwd(), I should use __dirname.
Your server.js is located in "dist" folder. So, please change the following line
const DIST_FOLDER = join(process.cwd(), 'dist');
to
const DIST_FOLDER = process.cwd();
I have developed nodejs express app. It is working fine when running on node server. But after hosting on iis server it always gives 'Bad Request' as response.
Get calls are working fine.
following is my web.conf file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<iisnode
nodeProcessCommandLine="C:\Program Files\nodejs\node.exe"
nodeProcessCountPerApplication="1"
maxConcurrentRequestsPerProcess="1024"
maxNamedPipeConnectionRetry="100"
namedPipeConnectionRetryDelay="250"
maxNamedPipeConnectionPoolSize="512"
maxNamedPipePooledConnectionAge="30000"
asyncCompletionThreadCount="0"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
watchedFiles="*.js;iisnode.yml"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="false"
logDirectory="iisnode"
debuggingEnabled="true"
debugHeaderEnabled="false"
debuggerPortRange="5058-6058"
debuggerPathSegment="debug"
maxLogFileSizeInKB="128"
maxTotalLogFileSizeInKB="1024"
maxLogFiles="20"
devErrorsEnabled="true"
flushResponse="false"
enableXFF="false"
promoteServerVars=""
configOverrides="iisnode.yml"
/>
<modules>
<remove name="WebDAVModule"/>
</modules>
</system.webServer>
</configuration>
server.js file as follows
'use strict';
// Module dependencies.
var express = require('express'),
path = require('path'),
fs = require('fs'),
methodOverride = require('method-override'),
morgan = require('morgan'),
bodyParser = require('body-parser');
var app = module.exports = exports.app = express();
app.locals.siteName = "IOS IBE";
app.use(express.static(__dirname + '/public'));
app.get('/*', function (req, res) {
res.sendFile(__dirname + '/public/index.html');
});
app.use(methodOverride());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
// Start server
var port = process.env.PORT;
app.listen(port, function () {
console.log('DP Admin server listening on port %d in %s mode', port, app.get('env'));
});
I could fixed this issue by adding
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
to web.config .
Hope this will help to any one else.