简体   繁体   中英

iisnode and cors on azure websites

I have an nodejs/expressjs Web API project setup that works perfectly fine when I test it using curl.

Here is the output for the local call:

dc-designer-client git:(master) curl -H "Origin: http://example.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose http://0.0.0.0:3000/api/grid
* Hostname was NOT found in DNS cache
*   Trying 0.0.0.0...
* Connected to 0.0.0.0 (127.0.0.1) port 3000 (#0)
> OPTIONS /api/grid HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 0.0.0.0:3000
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: GET
> Access-Control-Request-Headers: X-Requested-With
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
< Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With, *
< Content-Type: text/plain; charset=utf-8
< Content-Length: 2
< ETag: W/"2-4KoCHiHd29bYzs7HHpz1ZA"
< Date: Mon, 06 Jul 2015 01:24:01 GMT
< Connection: keep-alive
<
* Connection #0 to host 0.0.0.0 left intact

However when I deploy to azure and try executing the same curl statement, it gives me the following:

dc-designer-server git:(master) curl -H "Origin: http://example.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose http://dc-server.azurewebsites.net/api/grid
* Hostname was NOT found in DNS cache
*   Trying 23.96.124.25...
* Connected to dc-server.azurewebsites.net (127.0.0.1) port 80 (#0)
> OPTIONS /api/grid HTTP/1.1
> User-Agent: curl/7.37.1
> Host: dc-server.azurewebsites.net
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: GET
> Access-Control-Request-Headers: X-Requested-With
>
* Empty reply from server
* Connection #0 to host dc-server.azurewebsites.net left intact
curl: (52) Empty reply from server

I am sure this has to do with iisnode and iis on azure. What I don't know is how to configure the Azure WebSite to allow the OPTIONS preflight check to pass through to nodejs.

My server.js code is using the cors npm package. This code works locally when I configure nodejs and express but it seems that IIS on Azure is blocking or causing issues with my code.

Has anyone configured Azure WebSites using iisnode to allow for CORS calls?

I am using nodejs on Azure Websites. I've installed the cors package and enabled requests from all domains. Azure was still being blocking the CORS request.

I changed the web.config (each site has one, if one is not part of the deployment, then one is created). Per this stackoverflow post: HTTP OPTIONS request on Azure Websites fails due to CORS

My complete web.config below - There are setting specific to my site, so copying and pasting it won't work.

<?xml version="1.0" encoding="utf-8"?>
<!--
     This configuration file is required if iisnode is used to run node processes behind
     IIS or IIS Express.  For more information, visit:

     https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->

<configuration>
  <system.webServer>
    <!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
    <webSocket enabled="false" />
    <handlers>
      <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="transpiled/www.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <!-- Do not interfere with requests for node-inspector debugging -->
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^transpiled/www.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 site entry point -->
        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="transpiled/www.js"/>
        </rule>
      </rules>
    </rewrite>

    <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>

    <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />

    <!--
      You can control how Node is hosted within IIS using the following options:
        * watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
        * node_env: will be propagated to node as NODE_ENV environment variable
        * debuggingEnabled - controls whether the built-in debugger is enabled

      See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
    -->
    <!--<iisnode watchedFiles="web.config;*.js"/>-->

    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,OPTIONS" />
            <add name="Access-Control-Allow-Headers" value="Origin, X-Olaround-Debug-Mode, Authorization, Accept" />
            <add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" />
        </customHeaders>
    </httpProtocol>

  </system.webServer>
</configuration>

Copy this section and insert it just above the closing system.webServer tag.

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Olaround-Debug-Mode, Authorization, Accept" />
        <add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" />
    </customHeaders>
</httpProtocol>

To get the web.config, you'll have to deploy and then FTP into the instance. You can do this by clicking the "Download the publish profile" link from the site's dashboard.

Open the file up, it's xml.

<?xml version="1.0"?>
<publishData>
    <publishProfile profileName="secret - Web Deploy" publishMethod="MSDeploy" publishUrl="secret.scm.azurewebsites.net:443" msdeploySite="secret" userName="$secret" userPWD="v0ifRuLpeXf42kurCFHqXSA5uQnAdmx2c7lCHrrQPiyB6TxlXoG0dfJGFndH" destinationAppUrl="http://secret.azurewebsites.net" SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink="" webSystem="WebSites">
    <databases/>
</publishProfile>
<publishProfile profileName="secret - FTP" publishMethod="FTP" publishUrl="ftp://secret.ftp.azurewebsites.windows.net/site/wwwroot" ftpPassiveMode="True" userName="secret\$secret" userPWD="secret2c7lCHrrQPiyB6TxlXosecret" destinationAppUrl="http://secret.azurewebsites.net" SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink="" webSystem="WebSites">
<databases/>
</publishProfile>
</publishData>

In the publishProfile element for FTP, your find the url, username and password. Use the values in their entirety, otherwise it won't work.

Once you have the web.config, make changes and upload it back to the site. See if that works. It did for me.

For it to keep working, you'll need to add the web.config to the root of the project (or site). Otherwise Azure will blow it away on each deployment.

It turns out that you don't need to modify the default web.config for Azure IISNode to handle CORS requests.

In my server.js NodeJS code, I am using the standard CORS npm package. What I had to change to get my CORS requests to work across browsers was to change the protocol for my requests from "HTTP" to "HTTPS".

Once this change was made, I was able to use any browser as well as test my WebAPI using curl.

There is a sample here that sets up both a front end and back end site, and is set up with CORS. Specifically, this file has the logic.

That being said, this is a .NET sample. So it shows that it can work on Azure Web Apps in general, but I'm not sure whether there are special considerations related to IISNode.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM