From 31920f7d3e6598739abd927893d43fefd66dbecb Mon Sep 17 00:00:00 2001 From: Alexander Berger Date: Sun, 14 Apr 2024 21:10:51 -0400 Subject: [PATCH] Updating homepage and changing to linkout to api standards --- docs/assets/GW3-logo-2.png | Bin 0 -> 48256 bytes docs/assets/GW3-logo.png | Bin 0 -> 46744 bytes docs/index.md | 9 +- .../reference/api-standards/api-monitoring.md | 34 --- .../reference/api-standards/api-versioning.md | 152 ------------ docs/reference/api-standards/dns-naming.md | 130 ----------- .../reference/api-standards/error-handling.md | 219 ------------------ .../reference/api-standards/http-standards.md | 84 ------- docs/reference/api-standards/index.md | 18 -- .../api-standards/openapi-schemas.md | 95 -------- .../api-standards/restful-endpoint-naming.md | 87 ------- docs/reference/restful-api.md | 9 + mkdocs.yml | 9 - 13 files changed, 14 insertions(+), 832 deletions(-) create mode 100644 docs/assets/GW3-logo-2.png create mode 100644 docs/assets/GW3-logo.png delete mode 100644 docs/reference/api-standards/api-monitoring.md delete mode 100644 docs/reference/api-standards/api-versioning.md delete mode 100644 docs/reference/api-standards/dns-naming.md delete mode 100644 docs/reference/api-standards/error-handling.md delete mode 100644 docs/reference/api-standards/http-standards.md delete mode 100644 docs/reference/api-standards/index.md delete mode 100644 docs/reference/api-standards/openapi-schemas.md delete mode 100644 docs/reference/api-standards/restful-endpoint-naming.md diff --git a/docs/assets/GW3-logo-2.png b/docs/assets/GW3-logo-2.png new file mode 100644 index 0000000000000000000000000000000000000000..17cf3a7b2c26ab8dd422e0d8abe3974e3d94d286 GIT binary patch literal 48256 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 z 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
ExcYoSxt~bCMn;Awtz?*ByT?(7kkkrEu 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 NC3$tZQW?|0{|Ap#xqSct literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md index 7c5039a..34fbb0c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,6 @@

- GeneWeaver Logo - GeneWeaver + GeneWeaver Logo

@@ -38,15 +37,17 @@ [:octicons-arrow-right-24: NCI-60 Workflow](tutorial/nci_60_example_01/) + [:octicons-arrow-right-24: Mapping Gene Identifiers](tutorial/map-gene-ids.ipynb) + [:octicons-arrow-right-24: Authenticating With The Client Library](tutorial/geneweaver_client_login/) - :material-api:{ .lg .middle } __API Standards__ --- - Developed to be consistent with our open API Standards. + Developed to be consistent with The Jackson Laboratory's open source API Standards. - [:octicons-arrow-right-24: Standards Documentation](reference/api-standards/) + [:octicons-arrow-right-24: Standards Documentation](https://thejacksonlaboratory.github.io/api-standards/) - :material-scale-balance:{ .lg .middle } __Open Source, Apache License 2.0__ diff --git a/docs/reference/api-standards/api-monitoring.md b/docs/reference/api-standards/api-monitoring.md deleted file mode 100644 index 02b1468..0000000 --- a/docs/reference/api-standards/api-monitoring.md +++ /dev/null @@ -1,34 +0,0 @@ -# API Monitoring -> These guiding principles will help stability, uptime, and awareness for your applications. - -Actuator endpoints let you monitor and interact with your application. - -## Monitoring -Our endpoints for monitoring and info will exist at - -``` -/api/monitor// -``` - -## Health Endpoint - -**Required** - - -This endpoint provides health information, mainly the status of the application. It will be the -primary target for monitoring services. - -Location: -``` -http://127.0.0.1/api/monitor/server/health -``` -Example Response: -```` -{"name":"Fancy Application","status":"UP","details":"Everything seems okay."} -```` - -| Status Text | Http Status Code | -|--------------|------------------| -| `UP` | 200 | -| `UNKNOWN` | 200 | -| `DOWN` | 503 | diff --git a/docs/reference/api-standards/api-versioning.md b/docs/reference/api-standards/api-versioning.md deleted file mode 100644 index d84292c..0000000 --- a/docs/reference/api-standards/api-versioning.md +++ /dev/null @@ -1,152 +0,0 @@ -# API Versioning and Backwards Compatibility - -!!! success "Overview" - In order to prioritize simplicity, reliability, and maintainability we seek to - **minimize the need for API versioning** _as much as possible_. - -API versioning is a strategy to ensure that changes to the structure, -features, or behavior of an API (Application Programming Interface) do not break -applications that depend on it. APIs allow different software applications to -communicate and interact with each other, so changes to an API can have broad impacts. - -!!! tip - If your service has a single client, **which you control**, then you can avoid - versioning altogether. You also **do not** need to version APIs which have not yet - been released. - -!!! warning - This document talks about versioning API deployments, a process that is separate - from application release versioning, which is described in the - [Software Versions Document](/Operations/Best_Practices/software_versions/). - - In the context of application release versioning, this document describes the - process of incrementing the **major** version number. For example, going from - `v1.0.0` to `v2.0.0`. - - -## Guiding Principles - -1. **Minimal versioning**: We avoid versioning unless absolutely necessary. This - approach reduces complexity, both for the team developing the API and for those who - consume it. We strive, whenever possible, to make changes that are backwards - compatible. - -2. **Independent changes for reproducible science**: To support reproducible science, - it's essential that we can modify APIs without impacting the analysis. This principle - allows us to evolve our systems independently, providing robustness and flexibility. - -When versioning becomes unavoidable due to changes that can break existing clients, we -should follow the strategies provided in -this [guide](https://www.xmatters.com/blog/blog-four-rest-api-versioning-strategies/). - -!!! danger - Versioning is not a substitute for good API design. We should always strive to - design APIs that are flexible and extensible, and that can evolve without breaking - existing integrations. **Incrementing a major version should be a last resort.** - - -## Backwards Compatibility - -Backwards compatibility is as important as versioning. By maintaining backwards -compatibility, we allow API consumers to upgrade at their own pace without breaking -their existing integrations. Strategies to ensure backwards compatibility include: - -1. **Adding new fields**: When adding new data, do so by adding new fields that older - clients will simply ignore. The simplest way to do this is to add new fields that - have a default value. - -2. **Avoid removing fields**: Removing data fields may break existing integrations. It's - safer to deprecate old fields and leave them in place, while encouraging clients to - use new fields. - -3. **Keeping old endpoints**: If creating a new version of an endpoint, consider keeping - the old one for a time to allow clients to transition gradually. - -4. **Communicating changes**: Whenever a change is made that affects the API, it's - important to inform consumers in advance to give them time to adapt. - - -## Service Information Endpoint - -A service information endpoint is a valuable tool in API design, especially in terms of -API versioning and backwards compatibility. The service information endpoint provides a -clear way for client applications to understand the current state of the service, its -capabilities, and its versioning details. This enables clients to interact more -intelligently and efficiently with the service, adjusting their behavior based on the -information returned by this endpoint. - -Here's how a service information endpoint contributes to API versioning and backward -compatibility: - -1. **Communicating Version Information**: - The version of the API is often part of the service information. This makes it clear - to any consumers of the API what version they are interfacing with. Consumers can - then decide how to handle any changes based on the version information. This is where - an application would provide its deployed - [Software Version](/Operations/Best_Practices/software_versions/) number. - -2. **Facilitating Backward Compatibility**: - By communicating what features, workflows, and filesystem protocols are supported by - the service, a client application can adjust its behavior to only use features - supported by the current API version. This allows older clients to still function - correctly, even if new features or changes have been introduced in the latest version - of the API. - -3. **Providing Useful Metadata**: - Additional information such as the name, description, environment, and contact - details helps clients understand more about the service. For instance, it can help - debug issues (e.g., if the environment is "test", the behavior might be different - from a production environment). - -4. **Allowing Intelligent Client Behavior**: - In a more advanced use case, a client application might use the service information - to decide between different APIs or services. - -## When We Need to Version - -Despite our minimal versioning philosophy, there may be situations that require it. -These could include major architectural changes, the addition of new features that -aren't compatible with the current API design, or the nature of the system that's being -changed. - -In these cases, we should follow the versioning strategies outlined below. - -### Versioning Strategies - -When we need to introduce versioning, you might consider adopting one of the following -strategies: - -1. **URI Versioning**: In this strategy, the version information is included in the URI - itself. This is very simple and straightforward, but it can break URI consistency and - may cause confusion. - - 1. **URI Path**: This option involves including the version number as part of - the URI path. This allows clients to cache resources easily, but requires - branching the entire API when incrementing the version. - - 2. **Query Parameters**: This option involves including the version number as a - query parameter. This is straightforward to implement, but can become - difficult to manage across multiple endpoints. It also requires maintaining - all versions of the endpoints in a single application build. - -2. **Request Header Versioning**: This approach keeps the URI clean and includes the - version information in the request header. This preserves URI consistency, but it - requires consumers to add version information to their requests. - -3. **Media Type Versioning (Accept Header)**: This strategy requires the client to - specify the version in the Accept header. It offers clean URIs, but it may increase - complexity for clients. - -4. **Hypermedia As The Engine Of Application State (HATEOAS)**: This is the most complex - strategy, but it provides a lot of flexibility. It allows API consumers to navigate - APIs through hypermedia links. - -Remember, the choice of versioning strategy should be informed by our guiding -principles, the needs of our API consumers, and the nature of the changes that require -versioning. You should pick the strategy that best fits the situation of your -application and it's needs, and prioritize minimizing API versioning as much as -possible. - -!!! tip - For more information on possible versioning strategies, see this - [guide](https://www.xmatters.com/blog/blog-four-rest-api-versioning-strategies/). \ No newline at end of file diff --git a/docs/reference/api-standards/dns-naming.md b/docs/reference/api-standards/dns-naming.md deleted file mode 100644 index d893e6d..0000000 --- a/docs/reference/api-standards/dns-naming.md +++ /dev/null @@ -1,130 +0,0 @@ -# DNS Naming - -DNS (Domain Name System) is a system that translates human-friendly domain names, like -`www.jax.org`, into the numerical IP addresses needed for devices to load Internet -resources. This conversion process is often referred to as DNS name resolution, and it's -carried out by DNS servers. DNS serves as a sort of phonebook for the Internet, allowing -us to use memorable domain names while computers and other devices can handle the -underlying IP addresses they correspond to. - -Consistent DNS naming is important to maintaining API standards, both in terms of -operations and development. Consistent naming conventions enhance ease of use and -understanding of APIs, as intuitive and uniform naming conventions allow developers to -guess the correct endpoint, thereby reducing reliance on extensive documentation lookup. -Furthermore, DNS naming conventions enhances efficiency in both development and -maintenance as the risk of misconfiguration and mistakes drops when there -are standard conventions to follow in handling APIs. Another aspect is interoperability; -standard naming conventions ease integration with other systems and services as they -allow for a common language to be used. Finally, consistency in DNS naming aids in -service discovery, particularly in a microservices architecture in that it streamlines -categorization and comprehension of each service's purpose. - -## Naming Conventions -There is no single standard for DNS naming conventions that applications are _required_ -to follow, however, the following is the default convention that should be followed -unless there is a compelling reason to deviate from it. - -``` --.. -``` - -Where most applications will be hosted on `.jax.org` -``` --.jax.org -``` - -### Production DNS -For production environments, the application will also map a DNS name that **does not** -include the environment name. This is to allow for the use of the shorter DNS name -by most end users. - -``` -.. -``` - -Where most applications will be hosted on `.jax.org` -``` -.jax.org -``` - -### Frontend Clients and Backend APIs -One important consideration is to maintain a list that maps client applications (e.g., -web apps, CLI tools) to the backend services they employ. This also helps manage CORS -settings, if needed. This also helps to make it clear when specific frontend clients are -siblings of specific backend APIs. - -Where possible, it is preferred that the frontend client uses the same DNS name as the -backend API. This allows for intuitive discovery of the backend API by the frontend -client, and by developers, quality assurance, and operations personnel. - -!!! tip "Micro-service Architectures" - In a world of micro-services it's likely that we would move away from a one-to-one - mapping between a UI and an API. In theory services will be for specific purposes, - while clients may become more broad and integrated, pulling from multiple APIs. - - Data or analytic API’s should also be concerned with serving up other programmatic - clients, like scripts or Jupyter notebooks developed by an analyst. - -### Versioning -Versioning should be handled by the application itself, and **not by the DNS name**. -This allows for the application to be updated to a new version without requiring any -changes to the DNS name. - -!!! tip "Versioning Not Required" - Not all APIs will require versioning, and those that do not should not feel - compelled to implement it. Often, versioning can be avoided by careful design of the - API. - - Read more about API Versioning in the API Standards group's - [versioning document](/Development/Best_Practices/API_Standards/api_versioning/). - - -### Environments -The environment name should be one of the following: - -- `dev` - Development environment -- `sqa` - Testing environment -- `stage` - Staging environment -- `prod` - Production environment - -It is highly recommended to deploy each of the above environments, especially if your -application will rely on other applications, or if other applications will rely on your -application. This allows for your application, and those that depend on it, to always -have a matching environment for each deployment environment. - - -#### Staging/Production -The staging and production environments are special environments that should be as close -to identical as possible. The only difference between the two should be the data that -they are using. This is to ensure that any issues that are found in staging can be -reproduced in production. - -Depending on your application deployment model, these two environments can be viewed as -the "Blue" and "Green" in a "Blue/Green" deployment model. - -??? note "Blue/Green Deployments" - Blue/Green deployments are a type of software release management strategy designed to - reduce downtime and risk by running two identical production environments known as - Blue and Green. - - - Blue environment: This is the live production environment that is currently serving - user traffic. - - Green environment: This is the clone of the production environment where you deploy - the new version of the application. - - Initially, the Blue environment is live, serving all user traffic. When a new version - of the software is ready for release, it is deployed to the Green environment. - - Once the new version is tested and ready to go live, the router is switched to direct - all incoming traffic to the Green environment. The Green environment then becomes the - live or active environment. - - The Blue environment, now idle, can be used for preparation for the next release. - - -## Additional Considerations - -1) Applications should be hosted on port 80/443 so that the user does **not** need to -specify a port. -2) It's important to publicize if the application is hosted on an internal-only -IP address as this will affect the ability of users to access the application. diff --git a/docs/reference/api-standards/error-handling.md b/docs/reference/api-standards/error-handling.md deleted file mode 100644 index 49ca1a0..0000000 --- a/docs/reference/api-standards/error-handling.md +++ /dev/null @@ -1,219 +0,0 @@ -# REST API Error Handling Best Practices - -Error handling is crucial for ensuring the reliability and usability of a REST API service. Proper error handling not only helps developers identify and fix issues but also provides clear and informative responses to clients so they may take corrective action. - -## Guidelines -### 1. Use Appropriate HTTP Status Codes - -HTTP status codes are essential for conveying the outcome of API requests and allow a high level grouping of error responses. Use them consistently to indicate the result of each API call, and avoid using obscure codes that API consumers may not be familiar with. Common, widely used error codes provide clear semantics and promote consistency and interoperability. These include: - -- **400 Bad Request**: Malformed request syntax or invalid parameters -- **401 Unauthorized**: Authentication required or invalid credentials -- **403 Forbidden**: The authenticated user does not have permission to perform the operation -- **404 Not Found**: Requested resource does not exist -- **422 Unprocessable Content**: The request is formed correctly but there are semantical errors in the payload -- **500 Internal Server Error**: Generic server-side error - -### 2. Provide Detailed Error Messages - -When an error occurs, include detailed error messages in the response. These messages should provide enough information for consumers to understand the cause of the error and take appropriate actions. However, be cautious not to expose sensitive information or specifics that could be exploited by malicious users. For example, do not include implementation details or detailed stack traces. -**Error messages should clarify the problem and communicate the intended functionality**. For example, if a type check fails on an API to fetch a study record by id, the message "Study ID must be an integer" clearly conveys what is expected. - -### 3. Implement Consistent Error Response Format - -Follow a consistent error response format across all API endpoints, and format error response payloads as JSON. This makes it easier for clients to parse error responses and handle them gracefully. Include fields **status, request_id, error_code, message, timestamp, and trace_id** in your error responses. - -```json -{ - "status": "", HTTP Status Code for the entire request - "request_id": "", Request identifier generated by the API service - "errors": [{ - "error_code": "", Error code (see below) - "message": "", Human readable error details - "timestamp": "", Date/time of the error - "trace_id": "" Pointer to the log trace - }] -} -``` - -### 4. Return an errors array -It is possible for multiple errors to occur within one transaction, so for consistency return an errors collection even if there is only one error. - -### 5. Log Errors for Debugging - -Log errors on the server-side to aid in debugging and monitoring. Include relevant details like error message, error code, request URL, source, user ID (if available), stack trace, and timestamp. Log errors at appropriate severity levels based on the error's impact, for example "Critical", "Error", "Warning", "Info", "Debug". If you would like to learn about BioConnect's logging service, please reference the documentation [here](https://docs.bioconnect.jax.org/core-modules/logging-service/#the-logging-service). - -### 6. Error Codes -Use meaningful error codes in addition to HTTP status codes to provide more specific information. CS is developing a standard list of error codes that may be used across all of our software applications, providing the following benefits: -1. **Clarity and specificity**: HTTP status codes are useful but can be generic and lack context. In addition to providing status codes, error codes allow us to convey more detailed information about the nature of the error. -2. **Consistency**: By aligning on a standard list of error codes, we can ensure that error responses are uniform and predictable, which will make it easier for front end developers to handle errors and provide consistent messaging to users. -3. **Error reporting and troubleshooting**: If errors are properly logged, developers will be able to aggregate log data based on error codes, providing insight into errors that occur most frequently. - - - -The following examples show error codes, in combination with status codes and error messages: -1. invalid parameter - -```json -{ - "status": "400", - "request_id": "37472a48-a34e-4813-b064-f863170f33fc", - "errors": { - "error_code": "parameter_invalid", - "message": "Cannot convert 'abc' to integer", - "timestamp": "2023-07-02T14:07:01", - "trace_id": "fb3a02ac6caa" - } -} -``` - -2. value too large for column in database - -```json -{ - "status": "400", - "request_id": "a83e5e07-06b2-44f9-a18a-8eefdc3f9bf8", - "error": { - "error_code": "value_invalid", - "message": "animal name must be 50 characters or less", - "timestamp": "2023-08-24T01:10:00", - "trace_id": "3ff84c1df586" - - } -} -``` - -Below is the current working list of error codes for CS Rest APIs: - -400-Bad Request - -- parameter_missing -- parameter_invalid -- parameter_length_exceeded -- header_invalid - -401-Unauthorized - -- api_key_required -- api_key_invalid -- credentials_required -- credentials_invalid - -403-Forbidden - -- privileges_insufficient -- request_limit_exceeded - -404-Not found - -- url_invalid - -408-Timeout exceeded - -- timeout_exceeded - -422-Unprocessable content - -- value_missing -- value_invalid -- value_length_exceeded - - -## Use Cases/Examples - -**Missing/Invalid Parameters** -Consider an API that returns a list of animals based on a weight min and max value. A validation check is performed to ensure that both parameters are present and numeric. If the min value type check validation fails, a status code of 400 is returned, along with a "parameter_invalid" error code and the message "min value must be numeric". If the parameter is missing all together, the following response is issued: - -``` - min = request.query_params.get('min_value', None) - if min is None: - return Response( - { - "status": "400", - "request_id": "7abfde24-b2e8-49f9-af5b-5f45bd56cce3", - "errors":[ - { - "error": { - "error_code": "parameter_missing", - "message": "Minimum weight value is required", - "timestamp": "2023-09-24T01:10:00", - "trace_id": "48785f565a27" - } - } - ] - } - ) -``` -This example is a good use case for aggregating and reporting on error data in order to improve user experience. If your error logs are showing high numbers of "parameter_invalid" codes for a certain API, perhaps you should look into front end validation and constraints in order to prevent them. - - -**Insufficient Privileges** -It is important to remember that errors involving privileges fall under the 403 status code rather than 401. In the case of user based actions, a 401 status code essentially means "I don't recognize you" and 403 means "I know who you are but you're not allowed to do this." - -A typical use case involving insufficient privileges is an attempt to update a record when the user does not have read/write access to the data. The API logic should perform an authorization check before an attempt to update the record, and if not authorized, the response should inform the user that their request has been denied due to insufficient privileges. - -``` -return Response( - { - "status": "403", - "request_id": "5bbca962-1f57-4016-bac5-5ae9a28d7d2e", - "errors":[ - { - "error_code": "privileges_insufficient", - "message": "You do not have sufficient privileges to update this record", - "timestamp": "2023-09-24T01:10:00", - "trace_id": "48785f565a27" - } - ] - } -) -``` - -!!! tip "Not all 403 errors are tied to authenticated users" - They could also be used for anonymous actions that can only be performed under certain circumstances (eg time based restrictions.) Another example is a server that only accepts requests from a predefined range of IP addresses. - - -**Database Errors** -Database errors can be due to authentication/authorization issues, lost connection, or data integrity issues such as constraint violations. Database libraries often have some built in error handling that can be leveraged. When possible, you should catch and handle specific exceptions rather than generic "Exception" handlers. -Wrap database operations in try-except blocks to catch and handle exceptions, for example: -``` - try: - study= Study.objects.get(pk=study_id) - return Response({'identifier': study.identifier}) - except Item.DoesNotExist: - return Response( - { - "status": "404", - "request_id": "5bbca962-1f57-4016-bac5-5ae9a28d7d2e", - "errors":[ - { - ... - } - ] - } - ) -``` - -!!! tip "APIs should be idempotent" - There is no way to group requests together in a transaction in REST APIs. To compensate for this, you should endeavor to [make your APIs idempotent](https://restfulapi.net/idempotent-rest-apis/). With the exception of a POST request, sending the same request multiple times should produce the same result. To validate idempotency, implement test cases encompassing multiple invocations of the same request to ensure consistent outcomes irrespective of the number of executions. - -**Timeout** -Timeout errors can occur when there are network or service issues, or if a call to the API involves too much data. A retry mechanism may be used to handle timeout errors, although this would normally be handled in front end client code when a 504 (Gateway timeout) is received. If timeouts are occurring due to high server load, consider load balancing and scaling your application to ameliorate them. Also consider monitoring and alerts to notify you when timeouts become frequent. - -**Errors from 3rd Party Libraries** -When calling methods in a 3rd party library, you can follow best practices for handling specific errors provided you have visibility into the exceptions it may raise. Consider handling these errors with graceful degradation if it's possible for your application to continue to function when they occur, for example if you can't retrieve data use cached data as a fallback. If it's a 3rd party service and it's possible for it to be down, consider implementing a retry mechanism. -An API end point that makes a failed call to a 3rd party service should return a 200 response if the error was isolated to the 3rd party service. - -**Business Logic Failures** -If a request includes data that fails a back end business logic check, return a status code of 422 (Unprocessable Entity.) This indicates that the syntax is correct but the value(s) prevented the call from being successfully processed. Include data in the response indicating the specific failure. For example, and end point that creates an animal record expects a date of birth but the date provided is in the future and fails a business rule check. A "value_invalid" error code and message stating "Date of birth cannot be in the future" allows the client to correct the error. - - - - - - - - - - - diff --git a/docs/reference/api-standards/http-standards.md b/docs/reference/api-standards/http-standards.md deleted file mode 100644 index 72d8b80..0000000 --- a/docs/reference/api-standards/http-standards.md +++ /dev/null @@ -1,84 +0,0 @@ - -Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol used for -communication between web servers and clients, allowing for the transfer of data and -requests for resources over the internet. This document summarizes two important -sources of information for HTTP standards: - -- The Mozilla Developer Network (MDN) HTTP Reference[^1] -- The HTTP Semantics RFC (RFC 9110)[^2] - -## HTTP Methods - -### Common Implementation Methods -The following methods are commonly used for the endpoints we create in our web APIs. -They are useful for creating semantically meaningful RestFUL APIs. - -| Method | Type | Description | -|---------|-----------------------|---------------------------------------------------------------------------------------------------------------------------------| -| GET | Read Only, Idempotent | The GET method requests a representation of the specified resource. Requests using GET should **only retrieve data.** | -| HEAD | Read Only, Idempotent | The HEAD method asks for a response identical to a GET request, but **without the response body**. | -| POST | Non-idempotent | The POST method submits an entity to the specified resource, often **causing a change in state** or side effects on the server. | -| PUT | Idempotent | The PUT method **replaces** all current representations of the target resource with the request payload. | -| DELETE | Idempotent | The DELETE method **deletes** the specified resource. | -| PATCH | Non-idempotent | The PATCH method applies **partial modifications** to a resource. | - -### Common Operational Methods -These methods are most commonly handled by the web-frameworks/web-server and are not -typically used when implementing our own endpoints. - -| Method | Description | -|---------|-------------------------------------------------------------------------------------------| -| CONNECT | The CONNECT method establishes a tunnel to the server identified by the target resource. | -| OPTIONS | The OPTIONS method describes the communication options for the target resource. | -| TRACE | The TRACE method performs a message loop-back test along the path to the target resource. | - - -## HTTP Response Status Codes -We will list only the most relevant status codes here, but in general, we follow -the [mozilla guidelines](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). The -following descriptions are taken directly from the mozilla documentation. - - - -### 2xx Success -These codes indicate success. The three most common that we use are listed here, and -have only slight differences. - -| Status Code | Description | Long Description | -|-------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 200 | OK | The request succeeded. The result meaning of "success" depends on the HTTP method. | -| 201 | Created | The request succeeded, and a new resource was created as a result. This is typically the response sent after POST requests, or some PUT requests. | -| 204 | No Content | There is no content to send for this request, but the headers may be useful. The user agent may update its cached headers for this resource with the new ones. | - -### 4xx Client Error -These codes indicate that the server determined that client did something wrong with the -request. These are the most straightforward to implement from a backend perspective, -and provide the most information to the client about what went wrong. - -| Status Code | Description | Long Description | -|-------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 400 | Bad Request | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). | -| 401 | Unauthorized | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. | -| 403 | Forbidden | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. | -| 404 | Not Found | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. | -| 405 | Method Not Allowed | The request method is known by the server but is not supported by the target resource. For example, an API may not allow calling DELETE to remove a resource. | -| 409 | Conflict | This response is sent when a request conflicts with the current state of the server. | -| 422 | Unprocessable Entity | The request was well-formed but was unable to be followed due to semantic errors. | - -### 5xx Server Error -These codes indicate that the server had a problem processing the request. These are -the most difficult to implement from a backend perspective, and provide the least -information to the client about what went wrong. In general, when using one of these -codes, backend APIs should both log the associated error, and provide as much meaningful -information as possible to the client. - -| Status Code | Description | Long Description | -|-------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 500 | Internal Server Error | Internal Server Error | -| 501 | Not Implemented | The request method is not supported by the server and cannot be handled. The only methods that servers are required to support (and therefore that must not return this code) are GET and HEAD. | -| 502 | Bad Gateway | This error response means that the server, while working as a gateway to get a response needed to handle the request, got an invalid response. | -| 504 | Gateway Timeout | This error response is given when the server is acting as a gateway and cannot get a response in time. | - - -[^1]: [Mozilla: HTTP Status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) -[^2]: [RFC 9110 HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110) diff --git a/docs/reference/api-standards/index.md b/docs/reference/api-standards/index.md deleted file mode 100644 index 6d7ff36..0000000 --- a/docs/reference/api-standards/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: API Standards ---- - -# :material-api: API Standards -The API standards group is an open working group that is focused on creating a set of -standards for the development of APIs. - -The group is focused on exploring the following topics: - -* [x] [Standard HTTP Methods & Status Codes](http-standards/) -* [x] [Standard Naming of Domain Names](dns-naming/) -* [x] [Standard Naming of Endpoints](restful-endpoint-naming/) -* [x] [Define Scenarios and Categories of Response Errors](error-handling/) -* [x] [OpenAPI Schemas](openapi-schemas/) (FKA Swagger) -* [x] [Standard for API Versioning and Deprecation](api-versioning/) -* [x] [Standard for API Monitoring and Health](api-monitoring/) -* [ ] Testing of all items listed above. diff --git a/docs/reference/api-standards/openapi-schemas.md b/docs/reference/api-standards/openapi-schemas.md deleted file mode 100644 index 08959a9..0000000 --- a/docs/reference/api-standards/openapi-schemas.md +++ /dev/null @@ -1,95 +0,0 @@ -# OpenAPI Schemas - -!!! success "Overview" - As part of our commitment to creating well-defined, reliable, and easy-to-use APIs, - we adopt OpenAPI[^1] as a standard tool for defining, creating, and documenting our - APIs. OpenAPI helps our teams collaborate more efficiently, enhances the developer - experience, and maintains the quality of our APIs. This document lays out standards - and best practices around the usage and publication of OpenAPI schemas. - -## Why OpenAPI? - -OpenAPI[^1] is an industry-standard method for describing RESTful APIs. By requiring an -OpenAPI document[^2] for each API, we aim to: - -- **Increase Transparency**: With an OpenAPI document, every aspect of an API is clearly -described, from endpoints to response formats. This reduces guesswork and the potential -for misunderstandings. - -- **Streamline Collaboration**: Frontend and backend teams can reference the OpenAPI -document to understand what data is available, how to access it, and what kind of -responses to expect. - -- **Simplify Integration**: Other systems or third-party developers can use the OpenAPI -document to understand how to integrate with our APIs. - -- **Enable API Testing and Monitoring**: OpenAPI documents can be used to generate -testing scripts and monitor APIs for any discrepancies in expected behavior. - -- **Improve Developer Experience**: An OpenAPI document forms the basis for generating -interactive documentation, SDKs, and API explorers, enhancing the overall developer -experience. - -## Key Principles - -1. **Up-to-date Schema**: Each RESTful API must always provide an up-to-date -`openapi.json` file, reflecting the latest version of the API. - -2. **Automatic Generation**: The `openapi.json` file should be automatically generated -from the source code and annotations as part of the build pipeline. - -3. **Public Accessibility**: The `openapi.json` file should be easily accessible, -preferably through a dedicated endpoint (e.g., -`https://api.yourdomain.com/openapi.json`). - -4. **Auto-generated API Documentation**: The OpenAPI schema should be used to -automatically generate and update API navigator pages or interactive API documentation -(like Swagger UI). - -## Detailed Standards - -### OpenAPI File Generation - -- Use tools and libraries that support OpenAPI file generation from code annotations -(e.g., Swagger for Java or SpringFox). - -- The OpenAPI file should be generated as part of the build process. - -- Keep your annotations up-to-date as you make changes to your API. - -### OpenAPI File Hosting - -- The `openapi.json` file should be publicly accessible via a dedicated URL. - -- The file should be placed at a consistent location across all APIs for easy discovery - (e.g., `https://api.yourdomain.com/openapi.json`). - -- The server should deliver the `openapi.json` file with the correct MIME type -`application/json`. - -### Versioning - -- The OpenAPI document should reflect the current version of the API and be updated with -each version change. - -- If multiple versions of the API exist, each version should have its own `openapi.json` -file. - -### Auto-generated API Documentation - -- Use a tool like Swagger UI or ReDoc to automatically generate interactive API -documentation from the OpenAPI schema. - -- The documentation should be publicly accessible and updated automatically whenever the -OpenAPI schema is updated. - -- The documentation should provide interactive features such as the ability to send test -requests. - -!!! info - By adopting OpenAPI and following these standards and best practices, we can improve - the developer experience, enhance the discoverability of our APIs, and ensure our - documentation is always up-to-date. - -[^1]: [OpenAPI Initiative](https://www.openapis.org/) -[^2]: [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) diff --git a/docs/reference/api-standards/restful-endpoint-naming.md b/docs/reference/api-standards/restful-endpoint-naming.md deleted file mode 100644 index 24924d5..0000000 --- a/docs/reference/api-standards/restful-endpoint-naming.md +++ /dev/null @@ -1,87 +0,0 @@ -# RESTful API Endpoint Naming Standards - -!!! success "Overview" - The RESTful API Endpoint Naming Standards are a set of guidelines we follow - to maintain **consistency**, **clarity**, and **usability** in our APIs. - -Application Programming Interfaces (APIs) act as the gateways to data and capabilities -of our applications. With the REST architectural style, we can create scalable APIs that -are easy to consume and understand. - -Following a set of established naming conventions helps us create APIs that are -straightforward to use, which in turn accelerates development, minimizes the risk of -errors, and makes our services easier to consume. - -!!! tip - Although these are presented as standards, they should be considered as guidelines. - In specific cases, there might be valid reasons to deviate from these standards. - However, any deviation should be carefully considered and thoroughly discussed - within the team. - -## Guiding Principles - -1. **Resource Identification**: RESTful APIs use nouns (not verbs) to identify resources -or collections of resources. For example, use `/users` not `/getUsers` or `/createUser`. - -2. **Consistency**: Maintain consistent naming conventions across the API. This reduces -ambiguity and increases usability. - -3. **Plural Form Resources**: Resources should be named in plural form, such as `/users` -rather than `/user`. - -4. **Hierarchical Relationships**: Use sub-resources to show relationships between -resources. For example, to get a user's comments, you can use `/users/{id}/comments`. - -5. **Lowercase Letters**: Use lowercase letters for resources and collections. Mixed -case or camelCase can lead to confusion and errors. - -6. **Avoid Underscores (_)**: Underscores can sometimes be interpreted as spaces in -certain contexts and should be avoided. Use hyphens (-) for better readability if -needed[^2]. - -7. **No Trailing Slashes**: Trailing slashes should be avoided. For example, use -`/users` not `/users/`[^1]. - -8. **Non-CRUD Functions**: For routes that don't easily map to CRUD operations (Create, -Read, Update, Delete), consider mapping these to HTTP methods in a sensible way, or -group them under a sub-resource. For example, `/users/{id}/activate`. - -9. **Filters, Sorting, and Pagination**: For large collections, these should be -expressed as query parameters. For example, -`/users?status=active&sort=-registered&page=2`. - -10. **HTTP Status Codes**: Use appropriate HTTP status codes to indicate the status of -the request. For example, '200' for successful GET requests, '201' for successful POST -requests, '400' for bad requests, etc. - - !!! success "HTTP Status Codes" - For more information on the correct status codes to use, see the response - status codes section of the - [HTTP Standards page](/Development/Best_Practices/API_Standards/http_standards/#http-response-status-codes). - -11. **Error Handling**: Always return meaningful error messages and codes, helping the -consumer understand what went wrong and how they might fix it. - -!!! warning - Remember that these are **guidelines**, not hard rules. They serve as a starting - point for the API design, but each API has unique needs and may require certain - exceptions or adaptations. Always prioritize clarity, simplicity, and usability - when designing your API. - -## When Exceptions are Required - -Despite these guiding principles, there may be situations that require exceptions or -deviations. These could include compatibility with legacy systems, specific requirements -of certain clients, or other unique constraints. - -In such cases, exceptions should be carefully considered, thoroughly discussed within -the team, and clearly documented to avoid confusion and ensure everyone understands the -reasons behind the deviation. - -Always consider the potential impact of any exceptions on the overall usability, -clarity, and consistency of the API, and strive to minimize such deviations as much as -possible. - - -[^1]: [RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) -[^2]: [StackOverflow - Hyphens, Underscores, or Camel Case](https://stackoverflow.com/questions/10302179/hyphen-underscore-or-camelcase-as-word-delimiter-in-uris) \ No newline at end of file diff --git a/docs/reference/restful-api.md b/docs/reference/restful-api.md index 46c6eef..ccd9260 100644 --- a/docs/reference/restful-api.md +++ b/docs/reference/restful-api.md @@ -13,3 +13,12 @@ The API is available at [geneweaver-prod.jax.org/aon/api/docs](https://geneweaver-prod.jax.org/aon/api/docs). Read the paper [here](https://pubmed.ncbi.nlm.nih.gov/37891644/). + + +## API Standards + +GeneWeaver follows the API Standards set forth by The Jackson Laboratory. These +standards help to make using the GeneWeaver API easier and consistent. + +You can read more about the standards at the +[API Standards GitHub Repository](https://thejacksonlaboratory.github.io/api-standards/). diff --git a/mkdocs.yml b/mkdocs.yml index f6df332..41f3810 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -118,15 +118,6 @@ nav: - Logging In: reference/command-line/logging-in.md - API Commands: reference/command-line/api-commands.md - ReST API: reference/restful-api.md - - API Standards: - - reference/api-standards/index.md - - HTTP Standards: reference/api-standards/http-standards.md - - DNS Naming: reference/api-standards/dns-naming.md - - ReSTful Endpoint Naming: reference/api-standards/restful-endpoint-naming.md - - Response Errors: reference/api-standards/error-handling.md - - OpenAPI Schemas: reference/api-standards/openapi-schemas.md - - API Versioning: reference/api-standards/api-versioning.md - - API Monitoring: reference/api-standards/api-monitoring.md - Available Packages: reference/available-packages.md - Available Tools: reference/available-tools.md # - Scientific Workflows: reference/scientific-workflows.md