{ Community }
  • Academy
  • Docs
  • Developers
  • Resources
    • Community Articles
    • Apigee on GitHub
    • Code Samples
    • Videos & eBooks
    • Accelerator Methodology
  • Support
  • Ask a Question
  • Spaces
    • Product Announcements
    • General
    • Edge/API Management
    • Developer Portal (Drupal-based)
    • Developer Portal (Integrated)
    • API Design
    • APIM on Istio
    • Extensions
    • Business of APIs
    • Academy/Certification
    • Analytics
    • Events
    • Hybrid
    • Integration (AWS, PCF, Etc.)
    • Microgateway
    • Monetization
    • Private Cloud Deployment
    • Insights
    • IoT Apigee Link
    • BaaS/Usergrid
    • BaaS Transition/Migration
    • Apigee-127
    • New Customers
    • Topics
    • Questions
    • Articles
    • Ideas
    • Leaderboard
    • Badges
  • Log in
  • Sign up

Get answers, ideas, and support from the Apigee Community

  • Home /
  • Edge/API Management /
avatar image
4
Question by Michael Malloy · Sep 08, 2014 at 08:49 PM · 6.2k Views cors

Apigee Pre-Flight Options Requests

I create api proxies and check the box that says "Enable Direct Browser Access for Your API — Allow direct requests from a browser via CORS." but my OPTIONS requests are still failing with :

{
    "fault": {
        "faultstring": "Received 405 Response without Allow Header",
        "detail": {
            "errorcode": "protocol.http.Response405WithoutAllowHeader"
        }
    }
}	

From what I understand about CORS Pre-Flight Options requests, the client first sends the OPTIONS request to the server as a safeguard for "safe" CORS. This request should return a response with the list ofrequest types that are available.

My Question: How do I make it so that Apigee responds correctly to OPTIONS requests and does not pass the OPTIONS request to my api behind the proxy?. If it helps I have AngularJS javascript apps trying to communicate with my Apigee endpoint.

Javascript errors:

OPTIONS http://api.example.com No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://client.example.com' is therefore not allowed access.

XMLHttpRequest cannot load http://api.example.com No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://client.example.com' is therefore not allowed access. 


Default "Add CORS" xml

<AssignMessage async="false" continueOnError="false" enabled="true" name="Add-CORS">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Add>
        <Headers>
            <Header name="Access-Control-Allow-Origin">*</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Add>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

Default Proxy Endpoints xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows/>
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

Default Target Endpoint xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
    <Description/>
    <Flows/>
    <PreFlow name="PreFlow">
        <Request/>
        <Response>
            <Step>
                <Name>Add-CORS</Name>
            </Step>
        </Response>
    </PreFlow>
    <HTTPTargetConnection>
        <URL>http://api.example.com/v1/assets.json</URL>
    </HTTPTargetConnection>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</TargetEndpoint>
Comment
Add comment
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Close

3 Answers

  • Sort: 
avatar image
3
Best Answer

Answer by Michael Malloy   · Sep 08, 2014 at 08:57 PM

Since you don't want the OPTIONS request to pass through to the backend API, there are two things needed:

  1. A RouteRule to a null target with condition for the OPTIONS request. Notice there is no TargetEndpoint specified.
  2. A custom flow in the ProxyEndpoint to handle the CORS response. Since the new RouteRule sends the message to a null Target (echoes request back to client), the message will not route to the 'default' TargetEndpoint where the CORS policy currently is defined.

The route rule would look as follows:

<RouteRule name="NoRoute">
    <Condition>request.verb == "OPTIONS"</Condition>
</RouteRule>

An updated version of the ProxyEndpoint would look as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request/>
            <Response>
                <Step>
                    <Name>Add-CORS</Name>
                </Step>
            </Response>
        <Condition>request.verb == "OPTIONS"</Condition> 
        </Flow>
    </Flows>
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS"</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
   </RouteRule>
   <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

NOTE: The RouteRules are evaluated in the order specified in the ProxyEnpoint configuration. You should always have the default (no condition) Route at the end. Otherwise, if at the top, it will always match and never evaluate the other Route possibilities.

For now, you'd have to make the change any time you create a new proxy from the UI and need the full CORS support. Apigee needs to enhance the new API proxy builder to address this issue.

After this is resolved, folks may also run into: XMLHttpRequest cannot load <url>. The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:9090, *'. Origin 'http://localhost:9090' is therefore not allowed access. As outlined inaspnetwebstack.codeplex.com/workitem/1539 ... this happens when two "Access-Control-Allow-Origin" headers are getting added to the response. To resolve this, remove Add-CORS step from the TargetEndpoint's PreFlow's Response

Comment
Add comment Show 1 · Link
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Neha · Mar 23, 2016 at 01:08 PM 0
Link

It worked for me also. Thanks a lot :)

avatar image
0

Answer by Andrew Good · Nov 09, 2014 at 11:19 PM

@mmalloy @mmalloyapigeecom Thanks for this, it is really useful information. I am attempting to do a very similar request but am getting stuck on The 'Access-Control-Allow-Origin' header contains multiple values. I have removed the add-cors from the TargetEndpoints Preflow Response but not having much luck.

I am new to using Apigee so hopefully it is just something really simple I am missing!

Cheers,

Comment
Add comment · Link
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Jovani Arzate · Apr 10, 2019 at 06:32 AM

hey guys, I implemented something like that and it served me correctly.
In the proxy enpoint we must place in the preflow the next call of a Flowcallout to invoke a sharedflow which will have the policy of CORS

<PreFlow name="PreFlow">
<Request>
<Step>
<Name>FC-CORS</Name>
</Step>
<Step>
<Name>FC-OAuth2</Name>
</Step>
</Request>
<Response/>
</PreFlow>

Definition of flowcallout, where we invoke the sharedflow

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FlowCallout async="false" continueOnError="false" enabled="true" name="FC-CORS">
<DisplayName>FC-CORS</DisplayName>
<FaultRules/>
<Properties/>
<SharedFlowBundle>OPTIONS-CORS-Headers-Response</SharedFlowBundle>
</FlowCallout>

definition of sharedflow

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SharedFlow name="default">
<Step>
<Name>OPTIONS-CORS-Headers-Response</Name>
<Condition>request.verb == "OPTIONS"</Condition>
</Step>
</SharedFlow>

definition of the policy of raisefull, where we will indicate the headers of Access-Control-Allow-Origin with * that will allow the invocation from our browser

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="OPTIONS-CORS-Headers-Response">
<DisplayName>OPTIONS CORS Headers Response</DisplayName>
<Properties/>
<FaultResponse>
<Set>
<Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
<Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, ucsb-api-key, ucsb-api-version, authorization</Header>
<Header name="Access-Control-Max-Age">3628800</Header>
<Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
</Headers>
<Payload contentType="text/plain"/>
<StatusCode>200</StatusCode>
<ReasonPhrase>OK</ReasonPhrase>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

Regars

Comment
Add comment · Link
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Add headers (cors) to 401(etc) invalid token response 5 Answers

API Proxyreurns 200 but Response is empty when we make a call from different Origin 2 Answers

Enable request streaming for a specific route rather than entire proxy 2 Answers

CORs - Securing My Endpoint to only allow Apigee Edge 2 Answers

CORS issue while sending APIKEY as header. 1 Answer

  • Products
    • Edge - APIs
    • Insights - Big Data
    • Plans
  • Developers
    • Overview
    • Documentation
  • Resources
    • Overview
    • Blog
    • Apigee Institute
    • Academy
    • Documentation
  • Company
    • Overview
    • Press
    • Customers
    • Partners
    • Team
    • Events
    • Careers
    • Contact Us
  • Support
    • Support Overview
    • Documentation
    • Status
    • Edge Support Portal
    • Privacy Policy
    • Terms & Conditions
© 2020 Apigee Corp. All rights reserved. - Apigee Community Terms of Use - Powered by AnswerHub
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Create an article
  • Post an idea
  • Spaces
  • Product Announcements
  • General
  • Edge/API Management
  • Developer Portal (Drupal-based)
  • Developer Portal (Integrated)
  • API Design
  • APIM on Istio
  • Extensions
  • Business of APIs
  • Academy/Certification
  • Analytics
  • Events
  • Hybrid
  • Integration (AWS, PCF, Etc.)
  • Microgateway
  • Monetization
  • Private Cloud Deployment
  • Insights
  • IoT Apigee Link
  • BaaS/Usergrid
  • BaaS Transition/Migration
  • Apigee-127
  • New Customers
  • Explore
  • Topics
  • Questions
  • Articles
  • Ideas
  • Badges