Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

PI Web API Reference

Cross-Origin Resource Sharing

This topic explains CORS configuration in PI Web API, as well as instructions for setting up CORS correctly.

Background

Cross-Origin Resource Sharing (CORS) is a World Wide Web Consortium (W3C) specification for secure access to resources hosted in a remote domain. This was introduced to overcome the same-origin policy restriction imposed by most modern web browsers. The same-origin policy limits scripts running in one domain from accessing resources that are hosted in another for security purposes. For example, your application that runs on http://my-internal-site.internal/mygreatapp will not be allowed to make AJAX calls to PI Web API running at https://my-pisystem.internal/piwebapi since https://my-internal-site.internal and https://my-pisystem.internal have different origins.

If you are writing an application against PI Web API with scripts running on the browser (e.g., making an AJAX call in your JavaScript application) and seeing error messages in the browser console related to cross-origin requests, you need to enable CORS in the PI Web API configuration. Otherwise, the browser will prevent your script from accessing resources provided by PI Web API.

With CORS set up, the browser sends the request to the PI Web API server and determines whether the request is allowed based on CORS settings in PI Web API. There are two different ways that the browser can ask for permissions. For simplicity:

  • Simple cross-domain request: one HTTP request
  • Complex cross-domain request: two HTTP requests (preflight request + actual request). The preflight request is made automatically by the browser and uses the OPTIONS method. The actual request is only sent if the permission check is successful for the preflight request.

For more information about simple vs. complex requests, and about CORS in general, consult the following resources:

Configuration Settings

By default, CORS is disabled in PI Web API. To enable CORS or change CORS settings, choose one of the following actions:

  • Change the CORS related attributes in the AF configuration database under the element OSIsoft > PI Web API > (Your PI Web API Instance Name) > System Configuration.
  • Use the PUT action in the Configuration controller.

The following CORS configuration items are available in PI Web API:

  • CorsOrigins (default: null)

    The CorsOrigins attribute contains a comma-separated list of domains from which CORS requests may originate. In particular:

    • To indicate cross-domain requests cannot be accepted from any origin, use an empty string. (Effectively disables CORS.)
    • To indicate cross-domain requests are acceptable from any origins, use the asterisk (*) character for wildcard. (Not recommended.)

    Here is an example of a partial simple cross-domain request. The Origin header gives the domain of the site that is making the request.

    GET http://my-pisystem.internal/piwebapi HTTP/1.1
    Origin: http://my-internal-site.internal
    

    To allow this request, the CorsOrigins attribute in your PI Web API configuration needs to be set to the wildcard value *, or contain http://my-internal-site.internal in the list. If set correctly, the server will allow the request and set the Access-Control-Allow-Origin header. The value of this header either matches the Origin header, or is the wildcard value *. Here is a sample response:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://my-internal-site.internal
    

    If CorsOrigins attribute is not set correctly, the browser disallows the request and the response does not include the Access-Control-Allow-Origin header.

    Tips:

    • Check the Origin header in the request,and make sure the value matches with the header specified in the CorsOrigins attribute.
    • Make sure the origin is in correct URL format (e.g., "my-internal-site" is not a valid URL).
    • Do not include a space between the comma-separated list of origins.
    • Do not include a forward slash at the end of the origins URL.
    • Example configuration: http://my-internal-site.internal,http://my-internal-site2.internal:8080
  • CorsMethods (default: GET,OPTIONS)

    The CorsMethods attribute contains a comma-separated list of HTTP methods (verbs) that are allowed in cross-domain requests. In particular:

    • To indicate cross-domain requests cannot be accepted with any HTTP method, use an empty string. (Effectively disables CORS.)
    • To indicate that cross-domain requests are acceptable using any HTTP method, use the asterisk (*) character for wildcard.

    This is only used in a preflight request. Here is an example of a partial preflight cross-domain request.

    OPTIONS http://my-pisystem.internal/piwebapi/elements/I1EmDqD5loBNH0erqeqJodtALAaqQoQHk26BGgMQAVXYR0Ag HTTP/1.1
    Origin: http://my-internal-site.internal
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: authorization,content-type
    

    Note that it is an OPTION request (preflight). To allow this request, the CorsMethod attribute in your PI Web API configuration needs to be set to the wildcard value *, or contain PUT in the comma-separated list. (CorsHeader will be discussed in the next section.) If set correctly, the server will allow the request and set the Access-Control-Allow-Method header. Here is a sample response:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://my-internal-site.internal
    Access-Control-Allow-Methods: PUT
    Access-Control-Allow-Headers: authorization,content-type
    

    Following the preflight request, you will see the actual PUT request and response from the server, similar to the request and response you saw in the simple CORS request in the CorsOrigins section.

    Tips:

    • Check the Access-Control-Request-Method request header, and make sure the value matches with the method specified in the CorsMethods attribute.
    • Method names need to be in all upper case.
    • Do not include a space between the comma-separated list of methods.
    • Example configuration: GET,OPTIONS,POST
  • CorsHeaders (default: null)

    The CorsHeaders attribute contains a comma-separated list of HTTP header keys that are allowed for cross-domain requests. In particular:

    • To indicate cross-domain requests cannot be accepted with any HTTP headers, use a null or empty string.
    • To indicate that cross-domain requests can include any HTTP headers, use the asterisk (*) character for wildcard.

    Similar to CorsMethods, this is only used in the preflight request. Look at the sample preflight request in the CorsMethods section. To allow this request, the CorsHeader attribute in your PI Web API configuration needs to be set to the wildcard value *, or contain authorization and content-type in the comma-separated list. If set correctly, the server will allow the request and set the Access-Control-Allow-Headers header, as shown in the sample response above.

    Tips:

    • Check the Access-Control-Request-Headers value in the request, and make sure it matches with the headers specified in the CorsHeaders attribute.
    • Do not include a space between the comma-separated list of headers.
    • If you set CorsHeaders to anything other than \*, you should include at least add accept, content-type, and origin, plus any custom headers that you want to support. This is because browsers are not consistent in how they set Access-Control-Request-Headers.
    • Example configuration: accept,authorization,content-type,origin
  • CorsExposedHeaders (default: Allow,Content-Encoding,Content-Length,Date,Location)

    The CorsExposedHeaders attribute contains a comma-separated list of HTTP response headers that browsers are allowed to access in addition to the simple response headers exposed by the browser by default. The response headers that are available by default are:

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma

    To make other headers available to the application, include them in the list of CorsExposedHeaders attribute. For example, if you are creating an element using CreateElement and would like to get the url resource for the newly created element from the Location header, the Location header needs to be explicitly specified in CorsExposedHeaders because it is not exposed by default.

    Tips:

    • Do not confuse CorsExposedHeaders with CorsHeaders. The CorsHeaders attribute is used to specify the HTTP headers that are allowed in the requests, while the CorsExposedHeaders attribute is used to specify the HTTP headers that are exposed in the responses.
    • Do not include a space between the comma-separated list of headers.
    • Example configuration: Allow,Content-Encoding,Content-Length,Date,Location
  • CorsSupportsCredentials (default: false)

    The CorsSupportsCredentials attribute indicates whether the browser can send any user credentials with cross-domain requests.

    • False: authentication information sent from the browser is not allowed in the request.
    • True: authentication information sent from the browser is allowed in the request.

    An example response when the CorsSupportsCrendentials is set to true:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://my-internal-site.internal
    Access-Control-Allow-Methods: PUT
    Access-Control-Allow-Headers: authorization,content-type
    Access-Control-Allow-Credentials: true
    

    Tips:

    • CorsSupportsCredentials cannot be used in conjunction with a wildcard (*) value for CorsOrigins.
    • Set this flag to true if you are using Basic or Kerberos Authentication.
    • Example configuration: true
  • PreflightMaxAge (default: -1)

    PI Web API can indicate to client applications how long to cache the preflight request. Set to -1 to never send an Access-Control-Max-Age header in the preflight response. Set to 0 to instruct the client to never cache the preflight response.

Troubleshooting Tips

If you are troubleshooting CORS errors, the browser developer tools (usually opened by pressing F12) provide many useful ways to diagnose the error. Remember that the same-origin policy is a browser implementation, so different browsers may exhibit slightly different behaviors.

  1. Look at the error messages in the console. For example,

    • Chrome: XMLHttpRequest cannot load https://my-internal-site.internal/piwebapi. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://my-internal-site.internal' is therefore not allowed access. The response had HTTP status code 400.
    • Firefox: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https:// my-internal-site.internal/piwebapi. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
    • Internet Explorer: XMLHttpRequest: Network Error 0x80070005, Access is denied.
  2. The browser usually does not give us details on why the error occurs. Even though the browser specifically says that the CORS header Access-Control-Allow-Origin is missing, this does not mean that the CorsOrigins attribute is the culprit. This is because the server returns a generic response without any CORS headers if any of the CORS check fails.

  3. To identify the misconfigured CORS setting, inspect the request headers.

    • Make sure the value in the Origin header in the request matches with one of the origins specified in the CorsOrigins attribute (unless a wildcard is used).
    • Make sure the value in the Access-Control-Request-Method in the preflight request matches with one of the methods specified in the CorsMethods attribute (unless a wildcard is used).
    • Make sure the values in the Access-Control-Request-Headers in the preflight request match the headers specified in the CorsHeaders attribute (unless a wildcard is used).
    • If your client application is requesting for a specific header (e.g., Location), make sure it is included in the CorsExposedHeaders list.
    • Make sure CorsSupportsCredentials is true if you are using Basic or Kerberos authentication.
  4. Changing configuration setting does not require a restart of the PI Web API service since the service will update its configuration every 15 seconds or so. To make sure the new configuration values are accepted, check the admin logs in the event viewer for any errors and to verify the modified configuration values.

TitleResults for “How to create a CRG?”Also Available in