platform icon indicating copy to clipboard operation
platform copied to clipboard

Swagger documentation "try it out" is not working due to CORS problem

Open ilarimikkonen opened this issue 7 years ago • 2 comments

background: We have swagger documentation feature that has "try it out" feature. This allows users to try API from the browser.

problem: It is not working, because browser makes a preflight request and it fails with "failed to fetch" or similar error. This is bad UX.

desired behavior: Users can use the "try it out" & "execute" and they get a meaningful response

Solution proposal: It is possible to configure API umbrella so that headers are overwritten. There is an existing REST API that can be called to override the response headers for a particular method via PUT method and we have a wrapper for it.

Story: As a API owner, when the I go to advanced settings* and click "enable CORS support" values are fetched from API backend and prefilled to the text edit box with "x-api-key" as added header value. The text edit field is not visible until I click the "enable CORS support" tickbox. Then I can edit the value and hit save & publish button to set the config to proxy. If i don't understand what I'm doing, I can read descriptive help text explaining what is happening. If I want to disable CORS support, I click the tickbox and save&publish button and text edit field will disappear.

*things will look bit different in the "next" version

Before overriding the Access-control-allow-headers we need to do a OPTIONS method query to the API owner back end and see what values are returned. Then we need to append x-api-key to the "Access-control-allow-headers" list. The API backend server response needs to be checked every time values are changed via APInf. We need to provide a simple toggle "CORS ON/OFF" and additional text field allowing API owner to override the values at will. It may be that API backend is updated and then our of synch with umbrella settings. Additionally, when user enables this, we need to do the following: for all OPTIONS method queries, disable x-api-key requirement. Browser does not understand to set the x-api-key to the request when it does OPTIONS preflight request.

Explanation of the setting is also required: "Set "Access-control-allow-headers" value to enable Swagger documentation "try it out" feature. By enabling this feature API users can try the API from browser instead of terminal or Postman. If you update your backend settings, please remember to update values here by hitting the "Save&publish" button

when user clicks the tickbox ON, following needs to happen:

  • Do OPTIONS query to API backend
  • check the return value; if Access-control-allow-headers value is returned, proceed, otherwise show an error: "Unable to retrieve Access-control-allow-headers information from API backend. Please check your server settings and try again. + what ever came from the backend
  • get the API information If not ok, show error: "Unable to fetch API data from proxy"
  • Append "x-api-key" to Access-control-allow-headers list (if present and show in the UI)

when user hits the save & publish:

  • save the configuration

when user unticks, following needs to happen:

  • hide text field

when user unticks, following needs to happen:

  • remove the x-api-key from the
  • revert the "disable x-api-key for OPTIONS requests"
  • hide text field

If you want to try this with POSTMAN here is an example, pay attention to "sub_settings":

Needed headers: x-admin-auth-token, x-api-key

example body:

{ "api": { "backend_host": "devel3.t5.fi", "backend_protocol": "https", "balance_algorithm": "least_conn", "created_at": "2018-06-20T12:15:20Z", "created_by": "a14d55ab-906b-4769-aa29-e7301bbe20e0", "deleted_at": null, "frontend_host": "nightly.apinf.io:3002", "name": "ilari CORSSAA", "servers": [ { "host": "devel3.t5.fi", "port": 443, "id": "21a71d80-1171-4366-9bb4-866e6a406a38" } ], "settings": { "allowed_ips": null, "allowed_referers": null, "anonymous_rate_limit_behavior": null, "api_key_verification_level": null, "api_key_verification_transition_start_at": null, "append_query_string": null, "authenticated_rate_limit_behavior": null, "disable_api_key": false, "error_data": {}, "error_templates": {}, "http_basic_auth": null, "pass_api_key_header": null, "pass_api_key_query_param": null, "rate_limit_mode": "unlimited", "require_https": null, "require_https_transition_start_at": null, "required_roles": null, "required_roles_override": null, "error_data_yaml_strings": {}, "headers_string": "", "default_response_headers_string": "", "override_response_headers_string": "", "id": "6cd330ae-31c0-43e3-a69a-c9e4499e4283" }, "sort_order": 4840000, "sub_settings": [{ "http_method": "OPTIONS", "regex": ".*", "settings": { "allowed_ips": null, "allowed_referers": null, "anonymous_rate_limit_behavior": "ip_fallback", "api_key_verification_level": null, "api_key_verification_transition_start_at": null, "append_query_string": null, "authenticated_rate_limit_behavior": "all", "disable_api_key": true, "error_data": {}, "error_templates": {}, "http_basic_auth": null, "override_response_headers": [ { "key": "Access-control-allow-headers", "value": "X-Api-Key", "id": "4ffce302-3219-4378-8b9f-ae8b76e3161e" } ], "pass_api_key_header": null, "pass_api_key_query_param": null, "rate_limit_mode": null, "require_https": null, "require_https_transition_start_at": null, "required_roles": null, "required_roles_override": null, "error_data_yaml_strings": {}, "headers_string": "", "default_response_headers_string": "", "override_response_headers_string": "Access-control-allow-headers: X-Api-Key" }

        }],
    "updated_at": "2018-06-20T12:27:20Z",
    "updated_by": "9485bbe9-d41c-434a-a2d2-bd15532d62b5",
    "url_matches": [
        {
            "backend_prefix": "/api/rest/v1/",
            "frontend_prefix": "/managementrestapibeta3/",
            "id": "54c3f1dc-0085-49ca-ae85-6d14aae99fb9"
        }
    ],
    "version": 8,
    "id": "6d2711f0-89a4-453d-9476-1bf7bbcc5131",
    "creator": {
        "username": "[email protected]"
    },
    "updater": {
        "username": "[email protected]"
    }
}

}

additional documentation:

https://api-umbrella.readthedocs.io/en/latest/admin/api.html#!/api/put_api_umbrella_v1_apis_id https://medium.com/apinf/said-swagger-ui-browser-i-need-to-cors-what-options-do-i-have-5a9d6aa80ea4

this replaces issues: #2604 #3402 #2696

ilarimikkonen avatar Jul 20 '18 09:07 ilarimikkonen

latest plan is to do global solution with admin off / on switch.

ilarimikkonen avatar Aug 10 '18 10:08 ilarimikkonen

basically we now have swagger support (CORS) in latest umbrella. The status is that we have "undone" the trouble we introduce with umbrella. But if the API owner does not set correct headers (like Access control allow origin) the swagger will not work. Need to determine if we start messing more with the responses, give users options or leave it to the API owner to do and help with documentation

ilarimikkonen avatar Dec 03 '18 09:12 ilarimikkonen