Microsoft REST API Guidelines
Posted bosaidongmomo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Microsoft REST API Guidelines相关的知识,希望对你有一定的参考价值。
Microsoft REST API Guidelines
Microsoft REST API Guidelines Working Group
Name | Name | Name |
---|---|---|
Dave Campbell (CTO C+E) | Rick Rashid (CTO ASG) | John Shewchuk (Technical Fellow, TED HQ) |
Mark Russinovich (CTO Azure) | Steve Lucco (Technical Fellow, DevDiv) | Murali Krishnaprasad (Azure App Plat) |
Rob Howard (ASG) | Peter Torr (OSG) | Chris Mullins (ASG) |
Microsoft REST API Guidelines
1 Abstract
The Microsoft REST API Guidelines, as a design principle, encourages application developers to have resources accessible to them via a RESTful HTTP interface.
To provide the smoothest possible experience for developers on platforms following the Microsoft REST API Guidelines, REST APIs SHOULD follow consistent design guidelines to make using them easy and intuitive.
This document establishes the guidelines Microsoft REST APIs SHOULD follow so RESTful interfaces are developed consistently.
2 Table of contents
- Microsoft REST API Guidelines 2.3
- Microsoft REST API Guidelines
- 1 Abstract
- 2 Table of contents
- 3 Introduction
- 4 Interpreting the guidelines
- 5 Taxonomy
- 6 Client guidance
- 7 Consistency fundamentals
- 8 CORS
- 9 Collections
- 10 Delta queries
- 11 JSON standardizations
- 12 Versioning
- 13 Long running operations
- 14 Push notifications via webhooks
- 15 Unsupported requests
- 16 Appendix
3 Introduction
Developers access most Microsoft Cloud Platform resources via HTTP interfaces.
Although each service typically provides language-specific frameworks to wrap their APIs, all of their operations eventually boil down to HTTP requests.
Microsoft must support a wide range of clients and services and cannot rely on rich frameworks being available for every development environment.
Thus a goal of these guidelines is to ensure Microsoft REST APIs can be easily and consistently consumed by any client with basic HTTP support.
To provide the smoothest possible experience for developers, it’s important to have these APIs follow consistent design guidelines, thus making using them easy and intuitive.
This document establishes the guidelines to be followed by Microsoft REST API developers for developing such APIs consistently.
The benefits of consistency accrue in aggregate as well; consistency allows teams to leverage common code, patterns, documentation and design decisions.
These guidelines aim to achieve the following:
- Define consistent practices and patterns for all API endpoints across Microsoft.
- Adhere as closely as possible to accepted REST/HTTP best practices in the industry at-large.*
- Make accessing Microsoft Services via REST interfaces easy for all application developers.
- Allow service developers to leverage the prior work of other services to implement, test and document REST endpoints defined consistently.
- Allow for partners (e.g., non-Microsoft entities) to use these guidelines for their own REST endpoint design.
Note: The guidelines are designed to align with building services which comply with the REST architectural style, though they do not address or require building services that follow the REST constraints.
The term “REST” is used throughout this document to mean services that are in the spirit of REST rather than adhering to REST by the book.
3.1 Recommended reading
Understanding the philosophy behind the REST Architectural Style is recommended for developing good HTTP-based services.
If you are new to RESTful design, here are some good resources:
REST on Wikipedia – Overview of common definitions and core ideas behind REST.
REST Dissertation – The chapter on REST in Roy Fielding’s dissertation on Network Architecture, “Architectural Styles and the Design of Network-based Software Architectures”
RFC 7231 – Defines the specification for HTTP/1.1 semantics, and is considered the authoritative resource.
REST in Practice – Book on the fundamentals of REST.
4 Interpreting the guidelines
4.1 Application of the guidelines
These guidelines are applicable to any REST API exposed publicly by Microsoft or any partner service.
Private or internal APIs SHOULD also try to follow these guidelines because internal services tend to eventually be exposed publicly.
Consistency is valuable to not only external customers but also internal service consumers, and these guidelines offer best practices useful for any service.
There are legitimate reasons for exemption from these guidelines.
Obviously a REST service that implements or must interoperate with some externally defined REST API must be compatible with that API and not necessarily these guidelines.
Some services MAY also have special performance needs that require a different format, such as a binary protocol.
4.2 Guidelines for existing services and versioning of services
We do not recommend making a breaking change to a service that pre-dates these guidelines simply for compliance sake.
The service SHOULD try to become compliant at the next version release when compatibility is being broken anyway.
When a service adds a new API, that API SHOULD be consistent with the other APIs of the same version.
So if a service was written against version 1.0 of the guidelines, new APIs added incrementally to the service SHOULD also follow version 1.0. The service can then upgrade to align with the latest version of the guidelines at the service’s next major release.
4.3 Requirements language
The keywords “MUST,” “MUST NOT,” “REQUIRED,” “SHALL,” “SHALL NOT,” “SHOULD,” “SHOULD NOT,” “RECOMMENDED,” “MAY,” and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
4.4 License
This work is licensed under the Creative Commons Attribution 4.0 International License.
To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
5 Taxonomy
As part of onboarding to Microsoft REST API Guidelines, services MUST comply with the taxonomy defined below.
5.1 Errors
Errors, or more specifically Service Errors, are defined as a client passing invalid data to the service and the service correctly rejecting that data.
Examples include invalid credentials, incorrect parameters, unknown version IDs, or similar.
These are generally “4xx” HTTP error codes and are the result of a client passing incorrect or invalid data.
Errors do not contribute to overall API availability.
5.2 Faults
Faults, or more specifically Service Faults, are defined as the service failing to correctly return in response to a valid client request.
These are generally “5xx” HTTP error codes.
Faults do contribute to the overall API availability.
Calls that fail due to rate limiting or quota failures MUST NOT count as faults.
Calls that fail as the result of a service fast-failing requests (often for its own protection) do count as faults.
5.3 Latency
Latency is defined as how long a particular API call takes to complete, measured as closely to the client as possible.
This metric applies to both synchronous and asynchronous APIs in the same way.
For long running calls, the latency is measured on the initial request and measures how long that call (not the overall operation) takes to complete.
5.4 Time to complete
Services that expose long operations MUST track “Time to Complete” metrics around those operations.
5.5 Long running API faults
For a Long Running API, it’s possible for both the initial request to begin the operation and the request to retrieve the results to technically work (each passing back a 200), but for the underlying operation to have failed.
Long Running faults MUST roll up as Faults into the overall Availability metrics.
6 Client guidance
To ensure the best possible experience for clients talking to a REST service, clients SHOULD adhere to the following best practices:
6.1 Ignore rule
For loosely coupled clients where the exact shape of the data is not known before the call, if the server returns something the client wasn’t expecting, the client MUST safely ignore it.
Some services MAY add fields to responses without changing versions numbers.
Services that do so MUST make this clear in their documentation and clients MUST ignore unknown fields.
6.2 Variable order rule
Clients MUST NOT rely on the order in which data appears in JSON service responses.
For example, clients SHOULD be resilient to the reordering of fields within a JSON object.
When supported by the service, clients MAY request that data be returned in a specific order.
For example, services MAY support the use of the $orderBy querystring parameter to specify the order of elements within a JSON array.
Services MAY also explicitly specify the ordering of some elements as part of the service contract.
For example, a service MAY always return a JSON object’s “type” information as the first field in an object to simplify response parsing on the client.
Clients MAY rely on ordering behavior explicitly identified by the service.
6.3 Silent fail rule
Clients requesting OPTIONAL server functionality (such as optional headers) MUST be resilient to the server ignoring that particular functionality.
7 Consistency fundamentals
7.1 URL structure
Humans SHOULD be able to easily read and construct URLs.
This facilitates discovery and eases adoption on platforms without a well-supported client library.
An example of a well-structured URL is:
https://api.contoso.com/v1.0/people/jdoe@contoso.com/inbox
An example URL that is not friendly is:
https://api.contoso.com/EWS/OData/Users('jdoe@microsoft.com')/Folders('AAMkADdiYzI1MjUzLTk4MjQtNDQ1Yy05YjJkLWNlMzMzYmIzNTY0MwAuAAAAAACzMsPHYH6HQoSwfdpDx-2bAQCXhUk6PC1dS7AERFluCgBfAAABo58UAAA=')
A frequent pattern that comes up is the use of URLs as values.
Services MAY use URLs as values.
For example, the following is acceptable:
https://api.contoso.com/v1.0/items?url=https://resources.contoso.com/shoes/fancy
7.2 URL length
The HTTP 1.1 message format, defined in RFC 7230, in section 3.1.1, defines no length limit on the Request Line, which includes the target URL.
From the RFC:
HTTP does not place a predefined limit on the length of a
request-line. […] A server that receives a request-target longer than any URI it wishes to parse MUST respond
with a 414 (URI Too Long) status code.
Services that can generate URLs longer than 2,083 characters MUST make accommodations for the clients they wish to support.
Here are some sources for determining what target clients support:
- http://stackoverflow.com/a/417184
- https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
Also note that some technology stacks have hard and adjustable url limits, so keep this in mind as you design your services.
7.3 Canonical identifier
In addition to friendly URLs, resources that can be moved or be renamed SHOULD expose a URL that contains a unique stable identifier.
It MAY be necessary to interact with the service to obtain a stable URL from the friendly name for the resource, as in the case of the “/my” shortcut used by some services.
The stable identifier is not required to be a GUID.
An example of a URL containing a canonical identifier is:
https://api.contoso.com/v1.0/people/7011042402/inbox
7.4 Supported methods
Operations MUST use the proper HTTP methods whenever possible, and operation idempotency MUST be respected.
HTTP methods are frequently referred to as the HTTP verbs.
The terms are synonymous in this context, however the HTTP specification uses the term method.
Below is a list of methods that Microsoft REST services SHOULD support.
Not all resources will support all methods, but all resources using the methods below MUST conform to their usage.
Method | Description | Is Idempotent |
---|---|---|
GET | Return the current value of an object | True |
PUT | Replace an object, or create a named object, when applicable | True |
DELETE | Delete an object | True |
POST | Create a new object based on the data provided, or submit a command | False |
HEAD | Return metadata of an object for a GET response. Resources that support the GET method MAY support the HEAD method as well | True |
PATCH | Apply a partial update to an object | False |
OPTIONS | Get information about a request; see below for details. | True |
Table 1
7.4.1 POST
POST operations SHOULD support the Location response header to specify the location of any created resource that was not explicitly named, via the Location header.
As an example, imagine a service that allows creation of hosted servers, which will be named by the service:
POST http://api.contoso.com/account1/servers
The response would be something like:
201 Created
Location: http://api.contoso.com/account1/servers/server321
Where “server321” is the service-allocated server name.
Services MAY also return the full metadata for the created item in the response.
7.4.2 PATCH
PATCH has been standardized by IETF as the method to be used for updating an existing object incrementally (see RFC 5789).
Microsoft REST API Guidelines compliant APIs SHOULD support PATCH.
7.4.3 Creating resources via PATCH (UPSERT semantics)
Services that allow callers to specify key values on create SHOULD support UPSERT semantics, and those that do MUST support creating resources using PATCH.
Because PUT is defined as a complete replacement of the content, it is dangerous for clients to use PUT to modify data.
Clients that do not understand (and hence ignore) properties on a resource are not likely to provide them on a PUT when trying to update a resource, hence such properties could be inadvertently removed.
Services MAY optionally support PUT to update existing resources, but if they do they MUST use replacement semantics (that is, after the PUT, the resource’s properties MUST match what was provided in the request, including deleting any server properties that were not provided).
Under UPSERT semantics, a PATCH call to a nonexistent resource is handled by the server as a “create,” and a PATCH call to an existing resource is handled as an “update.” To ensure that an update request is not treated as a create or vice-versa, the client MAY specify precondition HTTP headers in the request.
The service MUST NOT treat a PATCH request as an insert if it contains an If-Match header and MUST NOT treat a PATCH request as an update if it contains an If-None-Match header with a value of “*”.
If a service does not support UPSERT, then a PATCH call against a resource that does not exist MUST result in an HTTP “409 Conflict” error.
7.4.4 Options and link headers
OPTIONS allows a client to retrieve information about a resource, at a minimum by returning the Allow header denoting the valid methods for this resource.
In addition, services SHOULD include a Link header (see RFC 5988) to point to documentation for the resource in question:
Link: <help>; rel="help"
Where help is the URL to a documentation resource.
For examples on use of OPTIONS, see preflighting CORS cross-domain calls.
7.5 Standard request headers
The table of request headers below SHOULD be used by Microsoft REST API Guidelines services.
Using these headers is not mandated, but if used they MUST be used consistently.
All header values MUST follow the syntax rules set forth in the specification where the header field is defined.
Many HTTP headers are defined in RFC7231, however a complete list of approved headers can be found in the IANA Header Registry."
Header | Type | Description |
---|---|---|
Authorization | String | Authorization header for the request |
Date | Date | Timestamp of the request, based on the client’s clock, in RFC 5322 date and time format. The server SHOULD NOT make any assumptions about the accuracy of the client’s clock. This header MAY be included in the request, but MUST be in this format when supplied. Greenwich Mean Time (GMT) MUST be used as the time zone reference for this header when it is provided. For example: Wed, 24 Aug 2016 18:41:30 GMT . Note that GMT is exactly equal to UTC (Coordinated Universal Time) for this purpose. |
Accept | Content type | The requested content type for the response such as:
|
Accept-Encoding | Gzip, deflate | REST endpoints SHOULD support GZIP and DEFLATE encoding, when applicable. For very large resources, services MAY ignore and return uncompressed data. |
Accept-Language | “en”, “es”, etc. | Specifies the preferred language for the response. Services are not required to support this, but if a service supports localization it MUST do so through the Accept-Language header. |
Accept-Charset | Charset type like “UTF-8” | Default is UTF-8, but services SHOULD be able to handle ISO-8859-1. |
Content-Type | Content type | Mime type of request body (PUT/POST/PATCH) |
Prefer | return=minimal, return=representation | If the return=minimal preference is specified, services SHOULD return an empty body in response to a successful insert or update. If return=representation is specified, services SHOULD return the created or updated resource in the response. Services SHOULD support this header if they have scenarios where clients would sometimes benefit from responses, but sometimes the response would impose too much of a hit on bandwidth. |
If-Match, If-None-Match, If-Range | String | Services that support updates to resources using optimistic concurrency control MUST support the If-Match header to do so. Services MAY also use other headers related to ETags as long as they follow the HTTP specification. |
7.6 Standard response headers
Services SHOULD return the following response headers, except where noted in the “required” column.
Response Header | Required | Description |
---|---|---|
Date | All responses | Timestamp the response was processed, based on the server’s clock, in RFC 5322 date and time format. This header MUST be included in the response. Greenwich Mean Time (GMT) MUST be used as the time zone reference for this header. For example: Wed, 24 Aug 2016 18:41:30 GMT . Note that GMT is exactly equal to UTC (Coordinated Universal Time) for this purpose. |
Content-Type | All responses | The content type |
Content-Encoding | All responses | GZIP or DEFLATE, as appropriate |
Preference-Applied | When specified in request | Whether a preference indicated in the Prefer request header was applied |
ETag | When the requested resource has an entity tag | The ETag response-header field provides the current value of the entity tag for the requested variant. Used with If-Match, If-None-Match and If-Range to implement optimistic concurrency control. |
7.7 Custom headers
Custom headers MUST NOT be required for the basic operation of a given API.
Some of the guidelines in this document prescribe the use of nonstandard HTTP headers.
In addition, some services MAY need to add extra functionality, which is exposed via HTTP headers.
The following guidelines help maintain consistency across usage of custom headers.
Headers that are not standard HTTP headers MUST have one of two formats:
- A generic format for headers that are registered as “provisional” with IANA (RFC 3864)
- A scoped format for headers that are too usage-specific for registration
These two formats are described below.
7.8 Specifying headers as query parameters
Some headers pose challenges for some scenarios such as AJAX clients, especially when making cross-domain calls where adding headers MAY not be supported.
As such, some headers MAY be accepted as Query Parameters in addition to headers, with the same naming as the header:
Not all headers make sense as query parameters, including most standard HTTP headers.
The criteria for considering when to accept headers as parameters are:
- Any custom headers MUST be also accepted as parameters.
- Required standard headers MAY be accepted as parameters.
- Required headers with security sensitivity (e.g., Authorization header) MIGHT NOT be appropriate as parameters; the service owner SHOULD evaluate these on a case-by-case basis.
The one exception to this rule is the Accept header.
It’s common practice to use a scheme with simple names instead of the full functionality described in the HTTP specification for Accept.
7.9 PII parameters
Consistent with their organization’s privacy policy, clients SHOULD NOT transmit personally identifiable information (PII) parameters in the URL (as part of path or query string) because this information can be inadvertently exposed via client, network, and server logs and other mechanisms.
Consequently, a service SHOULD accept PII parameters transmitted as headers.
However, there are many scenarios where the above recommendations cannot be followed due to client or software limitations.
To address these limitations, services SHOULD also accept these PII parameters as part of the URL consistent with the rest of these guidelines.
Services that accept PII parameters – whether in the URL or as headers – SHOULD be compliant with privacy policy specified by their organization’s engineering leadership.
This will typically include recommending that clients prefer headers for transmission and implementations adhere to special precautions to ensure that logs and other service data collection are properly handled.
7.10 Response formats
For organizations to have a successful platform, they must serve data in formats developers are accustomed to using, and in consistent ways that allow developers to handle responses with common code.
Web-based communication, especially when a mobile or other low-bandwidth client is involved, has moved quickly in the direction of JSON for a variety of reasons, including its tendency to be lighter weight and its ease of consumption with JavaScript-based clients.
JSON property names SHOULD be camelCased.
Services SHOULD provide JSON as the default encoding.
7.10.1 Clients-specified response format
In HTTP, response format SHOULD be requested by the client using the Accept header.
This is a hint, and the server MAY ignore it if it chooses to, even if this isn’t typical of well-behaved servers.
Clients MAY send multiple Accept headers and the service MAY choose one of them.
The default response format (no Accept header provided) SHOULD be application/json, and all services MUST support application/json.
Accept Header | Response type | Notes |
---|---|---|
application/json | Payload SHOULD be returned as JSON | Also accept text/javascript for JSONP cases |
GET https://api.contoso.com/v1.0/products/user
Accept: application/json
7.10.2 Error condition responses
For nonsuccess conditions, developers SHOULD be able to write one piece of code that handles errors consistently across different Microsoft REST API Guidelines services.
This allows building of simple and reliable infrastructure to handle exceptions as a separate flow from successful responses.
The following is based on the OData v4 JSON spec.
However, it is very generic and does not require specific OData constructs.
APIs SHOULD use this format even if they are not using other OData constructs.
The error response MUST be a single JSON object.
This object MUST have a name/value pair named “error.” The value MUST be a JSON object.
This object MUST contain name/value pairs with the names “code” and “message,” and it MAY contain name/value pairs with the names “target,” “details” and “innererror.”
The value for the “code” name/value pair is a language-independent string.
Its value is a service-defined error code that SHOULD be human-readable.
This code serves as a more specific indicator of the error than the HTTP error code specified in the response.
Services SHOULD have a relatively small number (about 20) of possible values for “code,” and all clients MUST be capable of handling all of them.
Most services will require a much larger number of more specific error codes, which are not interesting to all clients.
These error codes SHOULD be exposed in the “innererror” name/value pair as described below.
Introducing a new value for “code” that is visible to existing clients is a breaking change and requires a version increase.
Services can avoid breaking changes by adding new error codes to “innererror” instead.
The value for the “message” name/value pair MUST be a human-readable representation of the error.
It is intended as an aid to developers and is not suitable for exposure to end users.
Services wanting to expose a suitable message for end users MUST do so through an annotation or custom property.
Services SHOULD NOT localize “message” for the end user, because doing so MAY make the value unreadable to the app developer who may be logging the value, as well as make the value less searchable on the Internet.
The value for the “target” name/value pair is the target of the particular error (e.g., the name of the property in error).
The value for the “details” name/value pair MUST be an array of JSON objects that MUST contain name/value pairs for “code” and “message,” and MAY contain a name/value pair for “target,” as described above.
The objects in the “details” array usually represent distinct, related errors that occurred during the request.
See example below.
The value for the “innererror” name/value pair MUST be an object.
The contents of this object are service-defined.
Services wanting to return more specific errors than the root-level code MUST do so by including a name/value pair for “code” and a nested “innererror.” Each nested “innererror” object represents a higher level of detail than its parent.
When evaluating errors, clients MUST traverse through all of the nested “innererrors” and choose the deepest one that they understand.
This scheme allows services to introduce new error codes anywhere in the hierarchy without breaking backwards compatibility, so long as old error codes still appear.
The service MAY return different levels of depth and detail to different callers.
For example, in development environments, the deepest “innererror” MAY contain internal information that can help debug the service.
To guard against potential security concerns around information disclosure, services SHOULD take care not to expose too much detail unintentionally.
Error objects MAY also include custom server-defined name/value pairs that MAY be specific to the code.
Error types with custom server-defined properties SHOULD be declared in the service’s metadata document.
See example below.
Error responses MAY contain annotations in any of their JSON objects.
We recommend that for any transient errors that may be retried, services SHOULD include a Retry-After HTTP header indicating the minimum number of seconds that clients SHOULD wait before attempting the operation again.
ErrorResponse : Object
Property | Type | Required | Description |
---|---|---|---|
error | Error | ✔ | The error object. |
Error : Object
Property | Type | Required | Description |
---|---|---|---|
code | String (enumerated) | ✔ | One of a server-defined set of error codes. |
message | String | ✔ | A human-readable representation of the error. |
target | String | The target of the error. | |
details | Error[] | An array of details about specific errors that led to this reported error. | |
innererror | InnerError | An object containing more specific information than the current object about the error. |
InnerError : Object
Property | Type | Required | Description |
---|---|---|---|
code | String | A more specific error code than was provided by the containing error. | |
innererror | InnerError | An object containing more specific information than the current object about the error. |
Examples
Example of “innererror”:
"error":
"code": "BadArgument",
"message": "Previous passwords may not be reused",
"target": "password",
"innererror":
"code": "PasswordError",
"innererror":
"code": "PasswordDoesNotMeetPolicy",
"minLength": "6",
"maxLength": "64",
"characterTypes": ["lowerCase","upperCase","number","symbol"],
"minDistinctCharacterTypes": "2",
"innererror":
"code": "PasswordReuseNotAllowed"
In this example, the most basic error code is “BadArgument,” but for clients that are interested, there are more specific error codes in “innererror.”
The “PasswordReuseNotAllowed” code may have been added by the service at a later date, having previously only returned “PasswordDoesNotMeetPolicy.”
Existing clients do not break when the new error code is added, but new clients MAY take advantage of it.
The “PasswordDoesNotMeetPolicy” error also includes additional name/value pairs that allow the client to determine the server’s configuration, validate the user’s input programmatically, or present the server’s constraints to the user within the client’s own localized messaging.
Example of “details”:
"error":
"code": "BadArgument",
"message": "Multiple errors in ContactInfo data",
"target": "ContactInfo",
"details": [
"code": "NullValue",
"target": "PhoneNumber",
"message": "Phone number must not be null"
,
"code": "NullValue",
"target": "LastName",
"message": "Last name must not be null"
,
"code": "MalformedValue",
"target": "Address",
"message": "Address is not valid"
]
In this example there were multiple problems with the request, with each individual error listed in “details.”
7.11 HTTP Status Codes
Standard HTTP Status Codes SHOULD be used; see the HTTP Status Code definitions for more information.
7.12 Client library optional
Developers MUST be able to develop on a wide variety of platforms and languages, such as Windows, MacOS, Linux, C#, Python, Node.js, and Ruby.
Services SHOULD be able to be accessed from simple HTTP tools such as curl without significant effort.
Service developer portals SHOULD provide the equivalent of “Get Developer Token” to facilitate experimentation and curl support.
8 CORS
Services compliant with the Microsoft REST API Guidelines MUST support CORS (Cross Origin Resource Sharing).
Services SHOULD support an allowed origin of CORS * and enforce authorization through valid OAuth tokens.
Services SHOULD NOT support user credentials with origin validation.
There MAY be exceptions for special cases.
8.1 Client guidance
Web developers usually don’t need to do anything special to take advantage of CORS.
All of the handshake steps happen invisibly as part of the standard XMLHttpRequest calls they make.
Many other platforms, such as .NET, have integrated support for CORS.
8.1.1 Avoiding preflight
Because the CORS protocol can trigger preflight requests that add additional round trips to the server, performance-critical apps might be interested in avoiding them.
The spirit behind CORS is to avoid preflight for any simple cross-domain requests that old non-CORS-capable browsers were able to make.
All other requests require preflight.
A request is “simple” and avoids preflight if its method is GET, HEAD or POST, and if it doesn’t contain any request headers besides Accept, Accept-Language and Content-Language.
For POST requests, the Content-Type header is also allowed, but only if its value is “application/x-www-form-urlencoded,” “multipart/form-data” or “text/plain.”
For any other headers or values, a preflight request will happen.
8.2 Service guidance
At minimum, services MUST:
- Understand the Origin request header that browsers send on cross-domain requests, and the Access-Control-Request-Method request header that they send on preflight OPTIONS requests that check for access.
- If the Origin header is present in a request:
- If the request uses the OPTIONS method and contains the Access-Control-Request-Method header, then it is a preflight request intended to probe for access before the actual request. Otherwise, it is an actual request. For preflight requests, beyond performing the steps below to add headers, services MUST perform no additional processing and MUST return a 200 OK. For non-preflight requests, the headers below are added in addition to the request’s regular processing.
- Add an Access-Control-Allow-Origin header to the response, containing the same value as the Origin request header. Note that this requires services to dynamically generate the header value. Resources that do not require cookies or any other form of user credentials MAY respond with a wildcard asterisk (*) instead. Note that the wildcard is acceptable here only, and not for any of the other headers described below.
- If the caller requires access to a response header that is not in the set of simple response headers (Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma), then add an Access-Control-Expose-Headers header containing the list of additional response header names the client should have access to.
- If the request requires cookies, then add an Access-Control-Allow-Credentials header set to “true.”
- If the request was a preflight request (see first bullet), then the service MUST:
- Add an Access-Control-Allow-Headers response header containing the list of request header names the client is permitted to use. This list need only contain headers that are not in the set of simple request headers (Accept, Accept-Language, Content-Language). If there are no restrictions on headers the service accepts, the service MAY simply return the same value as the Access-Control-Request-Headers header sent by the client.
- Add an Access-Control-Allow-Methods response header containing the list of HTTP methods the caller is permitted to use.
Add an Access-Control-Max-Age pref response header containing the number of seconds for which this preflight response is valid (and hence can be avoided before subsequent actual requests). Note that while it is customary to use a large value like 2592000 (30 days), many browsers self-impose a much lower limit (e.g., five minutes).
Because browser preflight response caches are notoriously weak, the additional round trip from a preflight response hurts performance.
Services used by interactive Web clients where performance is critical SHOULD avoid patterns that cause a preflight request
-
For GET and HEAD calls, avoid requiring request headers that are not part of the simple set above. Allow them to be provided as query parameters instead.
- The Authorization header is not part of the simple set, so the authentication token MUST be sent through the “access_token” query parameter instead, for resources requiring authentication. Note that passing authentication tokens in the URL is not recommended, because it can lead to the token getting recorded in server logs and exposed to anyone with access to those logs. Services that accept authentication tokens through the URL MUST take steps to mitigate the security risks, such as using short-lived authentication tokens, suppressing the auth token from getting logged, and controlling access to server logs.
-
Avoid requiring cookies. XmlHttpRequest will only send cookies on cross-domain requests if the “withCredentials” attribute is set; this also causes a preflight request.
- Services that require cookie-based authentication MUST use a “dynamic canary” to secure all APIs that accept cookies.
-
For POST calls, prefer simple Content-Types in the set of (“application/x-www-form-urlencoded,” “multipart/form-data,” “text/plain”) where applicable. Any other Content-Type will induce a preflight request.
- Services MUST NOT contravene other API recommendations in the name of avoiding CORS preflight requests. In particular, in accordance with recommendations, most POST requests will actually require a preflight request due to the Content-Type.
- If eliminating preflight is critical, then a service MAY support alternative mechanisms for data transfer, but the RECOMMENDED approach MUST also be supported.
In addition, when appropriate services MAY support the JSONP pattern for simple, GET-only cross-domain access.
In JSONP, services take a parameter indicating the format (KaTeX parse error: Expected group after '_' at position 54: …ng a callback (_̲callback=someFunc), and return a text/javascript document containing the JSON response wrapped in a function call with the indicated name.
More on JSONP at Wikipedia: JSONP.
9 Collections
9.1 Item keys
Services MAY support durable identifiers for each item in the collection, and that identifier SHOULD be represented in JSON as “id”. These durable identifiers are often used as item keys.
Collections that support durable identifiers MAY support delta queries.
9.2 Serialization
Collections are represented in JSON using standard array notation.
9.3 Collection URL patterns
Collections are located directly under the service root when they are top level, or as a segment under another resource when scoped to that resource.
For example:
GET https://api.contoso.com/v1.0/people
Whenever possible, services MUST support the “/” pattern.
For example:
GET https://serviceRoot/collection/id
Where:
- serviceRoot – the combination of host (site URL) + the root path to the service
- collection – the name of the collection, unabbreviated, pluralized
- id – the value of the unique id property. When using the “/” pattern this MUST be the raw string/number/guid value with no quoting but properly escaped to fit in a URL segment.
9.3.1 Nested collections and properties
Collection items MAY contain other collections.
For example, a user collection MAY contain user resources that have multiple addresses:
GET https://api.contoso.com/v1.0/people/123/addresses
"value": [
"street": "1st Avenue", "city": "Seattle" ,
"street": "124th Ave NE", "city": "Redmond"
]
9.4 Big collections
As data grows, so do collections.
Planning for pagination is important for all services.
Therefore, when multiple pages are available, the serialization payload MUST contain the opaque URL for the next page as appropriate.
Refer to the paging guidance for more details.
Clients MUST be resilient to collection data being either paged or nonpaged for any given request.
"value":[
"id": "Item 1","price": 99.95,"sizes": null,
… ,
… ,
"id": "Item 99","price": 59.99,"sizes": null
],
"@nextLink": "opaqueUrl"
9.5 Changing collections
POST requests are not idempotent.
This means that two POST requests sent to a collection resource with exactly the same payload MAY lead to multiple items being created in that collection.
This is often the case for insert operations on items with a server-side generated id.
For example, the following request:
POST https://api.contoso.com/v1.0/people
Would lead to a response indicating the location of the new collection item:
201 Created
Location: https://api.contoso.com/v1.0/people/123
And once executed again, would likely lead to another resource:
201 Created
Location: https://api.contoso.com/v1.0/people/124
While a PUT request would require the indication of the collection item with the corresponding key instead:
PUT https://api.contoso.com/v1.0/people/123
9.6 Sorting collections
The results of a collection query MAY be sorted based on property values.
The property is determined by the value of the $orderBy query parameter.
The value of the $orderBy parameter contains a comma-separated list of expressions used to sort the items.
A special case of such an expression is a property path terminating on a primitive property.
The expression MAY include the suffix “asc” for ascending or “desc” for descending, separated from the property name by one or more spaces.
If “asc” or “desc” is not specified, the service MUST order by the specified property in ascending order.
NULL values MUST sort as “less than” non-NULL values.
Items MUST be sorted by the result values of the first expression, and then items with the same value for the first expression are sorted by the result value of the second expression, and so on.
The sort order is the inherent order for the type of the property.
For example:
GET https://api.contoso.com/v1.0/people?$orderBy=name
Will return all people sorted by name in ascending order.
For example:
GET https://api.contoso.com/v1.0/people?$orderBy=name desc
Will return all people sorted by name in descending order.
Sub-sorts can be specified by a comma-separated list of property names with OPTIONAL direction qualifier.
For example:
GET https://api.contoso.com/v1.0/people?$orderBy=name desc,hireDate
Will return all people sorted by name in descending order and a secondary sort order of hireDate in ascending order.
Sorting MUST compose with filtering such that:
GET https://api.contoso.com/v1.0/people?$filter=name eq 'david'&$orderBy=hireDate
Will return all people whose name is David sorted in ascending order by hireDate.
9.6.1 Interpreting a sorting expression
Sorting parameters MUST be consistent across pa
以上是关于Microsoft REST API Guidelines的主要内容,如果未能解决你的问题,请参考以下文章
Microsoft Graph REST API 来更新 Microsoft Planner 任务?