rubicon44TechBlog
    Search by

    API Design in Ruby on Rails.

    created_at:September 24, 2022

    updated_at:September 24, 2022

    Today, I am going to explain API design process.

    Purposes of this article creation

    • To be able to create API in Ruby on Rails on my own.
    • To be able to do API design.

    API Design Process

    In this case, I will create API specification for a SNS task management application on OpenAPI Specification as a deliverable.

    ※In this case, the OpenAPI Specification (formerly Swagger Specification) is used to create API specifications.

    ※OpenAPI allows defining endpoints, request URLs, HTTP methods, example response content, status codes, media types, and other things related to API specifications.

    【What is API Design?】

    • API Design is the process of developing an Application Programming Interface (API).
    • An API allows developers and users to use application function by the API’s developer releasing the API to the public.

    Difference between Web API and REST API

    • Broadly speaking, they mean the same thing.
    • A REST API is an API that is created in accordance with the REST principles of the Web architecture style.
    • APIs created with Web API are basically the same as REST API, but since they may not conform to the spirit of REST, Web API and REST API are strictly speaking different.
    • Currently, Web API is the mainstream.
    • Therefore, we are not overly concerned with the term REST.

    【What is Web API?】

    • An API that is invoked over a network using the HTTP protocol.

    【What is REST API?】

    • An API that can be accessed via HTTP and returns data in XML or JSON.

    Endpoint Design and Request Format

    1. Identify the functionality to be released as an API
    2. Determine the hostname and endpoint (when releasing as API, it is common to put “api” in the hostname)
    3. Consider OAuth authentication

    1. Identify the functionality to be released as an API

    【Task Management SNS Service】
    ※Omitted。

    2. Determine the hostname and endpoint (when releasing as API, it is common to put “api” in the hostname)

    ※In this section, the OpenAPI Specification is used to create the API specification.

    【Point】

    • URIs that are short and easy to type
    • URIs that can be read and understood by humans
    • URIs that are not mixed-case
    • URIs that are easy to modify (hackable)
    • URIs that do not reflect server-side architecture
    • URI with uniform rules

    【Deliverable】
    [Host name]
    https://api.grow-sns.com/v1/

    [Endpoints by function]
    ※Because of its large volume, the OpenAPI Specification is included at the end of the article.

    3. Consider OAuth authentication

    ※I am not currently considering OAuth authentication and will design it when it becomes necessary.

    Design response data (response body)

    1. Decide on the format of data to be used
    2. Decide what kind of data to actually return
    3. Decide whether data should be flat or hierarchical
    4. Unify the format (array or object)
    5. Unify the format of errors and decide on the error content

    1. Decide on the format of data to be used

    • The de facto standard for APIs in the world is now completely JSON.
    • We can see many services switching to JSON only, so it is no longer a problem as long as JSON is supported.
    • JSON is simpler than XML and requires a smaller size to represent the same data. It also works very well with JavaScript.

    【Deliverable】

    • Data format: JSON

    2. Decide what kind of data to actually return

    • Make it a list with user information, not just a list of IDs

      • Less access times
        • Easier for users to handle
        • Prevents application slowdowns due to increased HTTP overhead
        • Also, it prevents the server side load from increasing.
    • Allow users to choose the content of the response

      • Prevents the client from receiving a larger amount of data than necessary
      • Methods
        • Enable users to obtain necessary information by specifying query parameters
          • Method to let the user directly specify the name of each item
          • Method to prepare a response group and have the client specify the name of the response group.

    ※No need for an envelope; since HTTP plays the role of an envelope, the HTTP response body can be made to return the actual data.

    3. Decide whether data should be flat or hierarchical

    • It is better to keep it as flat as possible, but there are cases where a hierarchical structure is easier to understand.
      • The above is described in Google’s JSON Style Guide.
    • Avoid unnecessary hierarchies, as they increase the size of JSON data.

    4. Unify the format (array or object)

    • There are two ways to return an API response.

      • The way to return an array as is.
      • The method of wrapping the entire response as an object and placing the array inside the object.
    • There is no major problem with either method, but the method of wrapping the response in an object is recommended.

      • Advantages
        • It is easier to understand what the response data indicates.
        • Response data can be unified into an object.
        • Security risks can be avoided.
          • This is the most important point and is an effective countermeasure against JSON injection.

    5. Unify the format of errors and decide on the error content

    • It is too unkind to return only “an error occurred” when an error occurs.

      • As much information as possible should be returned to the client so that the client can resolve the problem and use the API.
    • Errors should not just return error information in the response body, but should first return an appropriate status code.

      • It should be as semantic as possible.
      • However, status codes are generic and general, and can only represent a category or summary of the error, so it is not possible to know what exactly the error actually was.
    • There are two main ways to return error content.

      • One is to return it in the HTTP response headers, and the other is to return it in the response body.
      • Considering the HTTP header and body structure as an envelope of data, it seems better to put error information in the header, but in reality, most open APIs use the method of storing error messages in the body.
      • This is thought to be because the body is easier to process from the client’s point of view.
    • At least, the error information to be returned should include a detailed error code and a link to detailed information, the information can be conveyed to the user.

    【Classification of status code】

    • 100-:Information
    • 200-:Success
    • 300-:Redirect
    • 400-:Error caused by client side
    • 500-:Error caused by server side

    Design HTTP response data (status line, response header)

    1. Determine status codes and use them correctly
    2. Decide if cache is used and if so, cache type
    3. Specify the media type
    4. Configure CORS settings

    ※You can also define your own HTTP headers.

    1. Determine status codes and use them correctly

    ※Status codes basically follow the HTTP specification.

    2. Decide if cache is used and if so, cache type

    ※The cache or not will be determined later.

    【Advantages of caching】

    • Increase the speed of the user experience because caching reduces communication to the server.
    • Service can be continued to some extent even when the network connection is down.
    • Lower communication costs for the user because caching reduces the number of communications to the server and the volume of transfers.
    • Server maintenance costs can be reduced by caching reducing the number of times the server is accessed.

    【Point】

    • When thinking about caching, we also need to be aware of proxy server.
      • A proxy server is one that is located between the client and server, and is functions as an intermediary in the exchange. In such cases, response data may be cached to reduce network traffic.

    【Cache type】

    • Expiration Model
    • Validation Model
    • Heuristic Expiration

    【If you don’t want them to cache】

    • You can use HTTP headers to explicitly tell the server that you do not want it to cache.

    3. Specify the media type

    • HTTP requests and responses must use media types to indicate the format of the body of data being sent.
    • Simply put, a media type is a data format, and is used to indicate what format the response data is in, whether it is JSON, XML, an image, or a simple text file.
    • In a response, it is used to specify the format of the data contained in the response body.
    • In the case of a request, it can specify what media types the client is capable of understanding.

    【Major media type】

    • text/plain:plain text
    • text/html:HTML document
    • application/json:JSON document
    • image/png:PNG image

    4. Configure CORS settings

    • XHTTPRequest cannot access and read response data for different domains.
      • This is due to a security policy called Same Origin Policy.
    • As a method for accessing different origins, a specification called CORS (Cross-Origin Resource Sharing) was developed.
      • CORS is more secure than JSONP and is an official specification.
    • To perform CORS, the client must first send a request header called Origin. The server side maintains a list of permitted access sources in advance and checks whether the source sent with the Origin header is included in the list.
      • If it is not included in the list, access is not allowed and a 403 error is returned.
      • If it is included in the list, the response header Access-Control-Allow-Origin is returned with the same originator as the Origin request header to indicate that access is allowed.

    Create a Web API that is easy to redesign

    1. Embed version control number in URI
    2. Determine guidelines for changing versions
    3. Determine guidelines for discontinuing the API and specifications for when the API is no longer provided

    1. Embed version control number in URI

    ※Host names are already defined in “Endpoint Design and Request Format”.

    【Example】

    - Version1.1:https://api.grow-sns.com/v1.1/

    【Point】

    • It is common to embed the version number at the beginning of the URI path.
    • It is easier to understand that it is a “version” if the version number is prefixed with “v”.
    • Include only “major numbers” in the URI.
      • Small changes should be handled in a backward-compatible manner without increasing the version number as much as possible.
      • Maintenance of multiple versions is costly and difficult for users to understand.
      • Methods to include minor versions in URIs such as Twitter and Facebook are minority.

    2. Determine guidelines for changing versions

    • As little versioning as possible.
      • Reduce maintenance costs for developers.
      • Reduce user support costs.
    • Changes that can be made to maintain backward compatibility are handled in minor versions of the same version whenever possible.

    ※This item may increase in the future.

    3. Determine guidelines for discontinuing the API and specifications for when the API is no longer provided

    • When the API is terminated, it will remain open for a minimum of 6 months.
    • When the API is closed, continuous announcements will be made regarding it.
    • When the API is closed, the status code 410 (Gone) is returned.
      • 410 means that the URI is no longer public.
      • The error message that “This API is no longer published. Please use a newer version.” etc. are returned.
      • Also, clearly state in the API documentation that “If 410 is returned, it means that the API is no longer published.

    ※I will not create the API documentation for now (I will create it when it becomes necessary).

    ※The most important issue this time is to create a portfolio.

    Create a robust Web API

    1. Implement HTTPS encryption
    2. Implement XSS countermeasures
    3. Implement XSRF countermeasures
    4. Implement JSON hijacking countermeasures
    5. Implement countermeasures against parameter tampering
    6. Implement countermeasures against request resending
    7. Implement countermeasures against mass access

    【Examples of security issues】

    • Unauthorized acquisition of information between server and client.
    • Unauthorized access or falsification of information due to server vulnerabilities.
    • Problems with APIs that are intended to be accessed from a browser.

    1. Implement HTTPS encryption

    • Purchase an official certificate and apply it to the URI.
    • HTTPS is a fairly effective means of addressing security issues.
    • Even if HTTPS is used, security cannot be guaranteed if it is not handled properly on the client side.

    2. Implement XSS countermeasures

    【What is XSS?】

    • XSS is the ability to execute JavaScript sent by the user when receiving user input and displaying it embedded in the HTML of the page.
    • If JavaScript is executed in the page, information stored in the browser, such as session cookies, can be easily accessed, the page can be tampered with, and the server can be accessed without the restrictions of the same origin policy.
    • Also note the same problem when returning JSON-like data as an API.
    • If the Content-Type of the returned JSON data is text/html, and the URI that returns this JSON data is directly accessed by a browser, this data will be interpreted as HTML, and the JavaScript described in the SCRIPT element will be executed.

    【Countermeasures】

    • User input, regardless of how it is used, should be properly checked.
    • When returning data to the user, also properly check the data content and remove strange values.
    • When returning JSON, make sure the Content-Type is application/json so that the browser can determine that the JSON is always JSON.
    • Use the response header X-Content-Type-Options to prevent JSON from being interpreted as HTML by Internet Explorer’s Content Sniffering feature (IE8 and later are supported).
    • To support IE7 and earlier browsers, data exchange in JSON usually uses XMLHttpRequest, with an additional request header check.
    • Escaping JSON strings such as <, >, /, \, , , Non-ASCII characters, +, etc. will eliminate the possibility of problems.

    3. Implement XSRF countermeasures

    【What is XSRF(Cross Site Request Forgery)?】

    • An attack that causes a server to perform a process that the user did not intend by sending forged requests across sites.
    • An attack that is expected to occur when an unspecified number of people access the site from which the attack originates.

    【Countermeasures】

    • For accesses that change data on the server side (e.g., adding a favorite, posting on a bulletin board, etc.), POST, PUT, or DELETE should be used instead of the GET method.
      • This makes it impossible to embed attack code using IMG elements, etc.
      • Not using the GET method for changes that affect the server side is one of the things that must be done, both for the sake of HTTP etiquette and to prevent search engines and other crawlers, in addition to XSRF, from doing bad things to the server.
    • The most commonly used XSRF countermeasure is the use of XSRF tokens.
      • This is a method that embed one-time token issued by the site, or at least a unique token for each session in the legitimate Form, and any access without the token is denied.
      • This increases security because it prevents unspecified people from accessing the site with common parameters.
      • This prevents the attacker from being able to launch the attack using the FORM element or POST method, which are not affected by the same origin policy even if also take measures not to use the GET method.
    • If the Web API is intended to be accessed only by XMLHttpRequest or by clients other than browsers, a method can be used to incorporate a specification that requires the client to attach a special request header and deny access if that header is not present.
      • Check X-Requested-With to deny access if not present.
      • In the case of POST from the FORM element, XSRF by the form can be prevented because the form cannot be sent with any headers.

    4. Implement JSON hijacking countermeasures

    【What is JSON hijacking?】

    • Information sent in JSON from the API can be stolen by a malicious third party.
      • This is possible because the same origin policy is not applied to the SCRIPT element.
      • Various techniques can be used to read the data.

    [JSON hijacking techniques]

    • The method changing the constructor of an Array object (※This technique existed in Firefox 2.0 and is no longer possible in current browsers).
    • The method using an object setter.

    【Countermeasures】

    • JSON should not be read by the SCRIPT element.
      • You can disallow access to JSON unless it has a special header (e.g., X-Requested-With).
    • Make sure that browsers recognize JSON as JSON.
      • Return the correct media type (application/json) to the client.
      • Also add X-Content-Type-Options introduced in IE8.
    • Make JSON uninterpretable as JavaScript, or prevent data from being read at runtime.
      • When JSON is specified as a SCRIPT element, it cannot be parsed and an error occurs, or it falls into an infinite loop at runtime, and the data reading process is not performed.
      • The simplest countermeasure is to return an object instead of an array of JSON.
      • Objects are syntactically incorrect as JavaScript, so an error will occur if the top level of the JSON data is an object.
    • A method to prevent processing from progressing when reading a JSON file by setting up an infinite loop, etc. at the top of the JSON file.
      • When reading in JSON, delete “for (;;) ;” at the beginning of the JSON file by string manipulation before use.
      • The Facebook data not only contains an infinite loop at the beginning, but also reduces the number of HTTP requests by loading multiple JSON data in rows at once.
      • The method of inserting an infinite loop may be a realistic solution that serves as a last bulwark even in the unlikely event that the JSON data loaded by the SCRIPT element does not cause a syntax error as JavaScript.
      • This method is not recommended for APIs that accept access from third parties, but can be considered for JSON endpoints in web services and APIs for SSKDs.

    5. Implement countermeasures against parameter tampering

    【What is parameter tampering?】

    • Changing the parameters to be sent to the server without permission, thereby obtaining information that cannot be obtained originally, or changing the data on the server side to values that are not originally possible.

    【Countermeasures】

    • Information that should not be accessible should be properly checked on the server side and access should be prohibited.
    • Information sent from the client should not be trusted, and its integrity should be properly checked on the server side.
      • It may be necessary to send information to enable verification at the same time.

    ※Do not be careless with APIs that do not disclose their specifications.

    6. Implement countermeasures against request resending

    【What is resubmitting a request?】

    • Sending a request once sent again causes the server to perform the same process again.

    【Countermeasures】

    • Since resending a request is an access attempt using the same URI, the same parameters, and the same header information as once succeeded, unlike parameter tampering, it may be impossible to determine if the parameters are appropriate. Therefore, for each API, it is necessary to determine whether or not repeated accesses to it will cause a problem, and for those that may cause a problem, it is necessary to manage the status and properly check for errors if the same access is made repeatedly.
      • In some cases, it is also effective to process such as not counting after the second access.

    7. Implement countermeasures against mass access

    【What is mass access?】

    • When a server receives a large number of accesses, its resources are forced to work harder to handle the accesses, and eventually it becomes unable to handle the load and no one can connect to the server at all.
    • DoS attacks take advantage of this.

    【Countermeasures】

    • Limit access per user.
      • Set a rate limit (maximum number of accesses) and return an error if accesses exceed the rate limit.
      • What should be decided when setting a rate limit?
        • What to use to identify users.
        • How many limit values should be set.
        • In what units to set the limit value.
        • When to reset the limit.
      • How to handle the case when the limit is exceeded?
        • Return “429 Too Many Requests” HTTP status code.
        • Add a Retry-After header to clarify how much time should be waited before re-accessing.
        • Some APIs use status codes other than 429.

    What to do when publishing a Web API

    • Provide API Documentation

    Provides API documentation

    【Notes】

    • Keep the API documentation up-to-date.

    ※It is very useful to include sample code as well.

    Deliverables(API Specification)

    • URL:NONE.

    References

    [Differences between REST and RESTful]

    [HTTP Request]

    [API Design]

    [OpenAPI Specification]

    [Others]

    Word Explanation

    NONE.

    Summary/What I learned this time

    【Summary】
    When actually implementing the API, be sure to take into account the parts of the API that are not defined in the OpenAPI Specification.

    【What I learned this time】
    NONE.

    Endpoints by function(OpenAPI Specification)

    openapi: 3.0.0
    info:
      title: grow-sns
      version: '1.0'
    servers: []
    
    paths:
      /api/v1/users/sign_in:
        post:
          tags:
            - signin
          summary: Create a idToken
          description: Returns a idToken
          operationId: post-sign_in
          parameters:
            - name: idToken
              in: header
              required: true
              schema:
                type: string
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/UserSignIn'
      /api/v1/users:
        get:
          tags:
            - user
          summary: Find all user
          description: Returns all user
          operationId: get-users
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Users'
            '404':
              description: Users not found
          security:
            - ApiKeyAuth: []
        post:
          tags:
            - user
          summary: Create a new user
          description: Create a new user
          operationId: post-user
          requestBody:
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/NewUser'
          responses:
            '201':
              description: Created
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/UserAfterCreate'
      /api/v1/{username}:
        get:
          tags:
            - user
          summary: Find a user by username
          description: Returns a single user
          operationId: get-user
          parameters:
            - name: username
              in: path
              required: true
              schema:
                type: string
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/User'
            '400':
              description: Invalid username supplied
            '404':
              description: User not found
          security:
            - ApiKeyAuth: []
        put:
          tags:
            - user
          summary: Update an existing user
          description: Update an existing user by username
          operationId: update-user
          parameters:
            - name: username
              in: path
              required: true
              schema:
                type: string
          requestBody:
            description: Update an existent user
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/User'
            required: true
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/User'
            '400':
              description: Invalid username supplied
            '404':
              description: User not found
          security:
            - ApiKeyAuth: []
      /api/v1/tasks:
        get:
          tags:
            - task
          summary: Find tasks
          description: Returns all tasks
          operationId: get-tasks
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Tasks'
            '404':
              description: Tasks not found
          security:
            - ApiKeyAuth: []
        post:
          tags:
            - task
          summary: Create a new task
          description: Create a new task
          operationId: post-task
          requestBody:
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Task'
          responses:
            '201':
              description: Created
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Task'
      /api/v1/tasks/{id}:
        get:
          tags:
            - task
          summary: Find a task
          description: Returns a task
          operationId: get-task
          parameters:
            - name: id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Task'
            '404':
              description: Task not found
          security:
            - ApiKeyAuth: []
        put:
          tags:
            - task
          summary: Update an existing task
          description: Update an existing task by id
          operationId: update-task
          parameters:
            - name: id
              in: path
              required: true
              schema:
                type: integer
          requestBody:
            description: Update an existent task
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Task'
            required: true
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Task'
            '400':
              description: Invalid id supplied
            '404':
              description: Task not found
          security:
            - ApiKeyAuth: []
        delete:
          tags:
            - task
          summary: Deletes a task
          description: delete a task
          operationId: delete-task
          parameters:
            - name: id
              in: path
              description: Task id to delete
              required: true
              schema:
                type: integer
          responses:
            '204':
              description: No Content
          security:
            - ApiKeyAuth: []
      /api/v1/tasks/{task_id}/likes:
        get:
          tags:
            - like
          summary: Find likes
          description: Returns likes
          operationId: get-likes
          parameters:
            - name: task_id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Likes'
            '404':
              description: Likes not found
          security:
            - ApiKeyAuth: []
        post:
          tags:
            - like
          summary: Create a new like
          description: Create a new like
          operationId: post-like
          parameters:
            - name: task_id
              in: path
              required: true
              schema:
                type: integer
          requestBody:
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Like'
          responses:
            '201':
              description: Created
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Like'
      /api/v1/tasks/{task_id}/likes{id}:
        delete:
          tags:
            - like
          summary: Deletes a like
          description: delete a like
          operationId: delete-like
          parameters:
            - name: task_id
              in: path
              required: true
              schema:
                type: integer
            - name: id
              in: path
              description: Like id to delete
              required: true
              schema:
                type: integer
          responses:
            '204':
              description: No Content
          security:
            - ApiKeyAuth: []
      /api/v1/users/{user_id}/relationships:
        post:
          tags:
            - relationship
          summary: Create a new relationship
          description: Create a new relationship
          operationId: post-relationship
          parameters:
            - name: user_id
              in: path
              required: true
              schema:
                type: integer
          requestBody:
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Relationship'
          responses:
            '201':
              description: Created
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Relationship'
        delete:
          tags:
            - relationship
          summary: Deletes a relationship
          description: delete a relationship
          operationId: delete-relationship
          parameters:
            - name: user_id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '204':
              description: No Content
          security:
            - ApiKeyAuth: []
      /api/v1/users/{id}/followings:
        get:
          tags:
            - relationship
          summary: Find followings
          description: Returns followings
          operationId: get-followings
          parameters:
            - name: id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Relationships'
            '404':
              description: Followings not found
          security:
            - ApiKeyAuth: []
      /api/v1/users/{id}/followers:
         get:
          tags:
            - relationship
          summary: Find followers
          description: Returns followers
          operationId: get-followers
          parameters:
            - name: id
              in: path
              required: true
              schema:
                type: integer
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Relationships'
            '404':
              description: Followers not found
          security:
            - ApiKeyAuth: []
      /api/v1/notifications:
        get:
          tags:
            - notification
          summary: Find notifications
          description: Returns notifications
          operationId: get-notifications
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Notifications'
            '404':
              description: Notifications not found
          security:
            - ApiKeyAuth: []
        # post:
      /api/v1/searches:
        get:
          tags:
            - search
          summary: Search value
          description: Returns search result
          operationId: get-search-result
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    # type: array
                    # items:
                      $ref: '#/components/schemas/Tasks'
                      # Not supported multiple $ref in Swagger.
                      # $ref: '#/components/schemas/Users'
            '404':
              description: Searches not found
          security:
            - ApiKeyAuth: []
    
    components:
      securitySchemes:
        ApiKeyAuth:
          type: apiKey
          in: header
          name: Authorization
      schemas:
        UserSignIn:
          title: UserSignIn
          type: object
          properties:
            token:
              type: string
              example: 1HUPqJIISZxnZunShlSISenP1HUPqJIISZxnZunShlSISenP1HUPqJIISZxnZunShlSISenP1HUPqJIISZxnZunShlSISenP1HUPqJIISZxnZunShlSISenP
            user:
              allOf:
                - type: object
                - $ref: '#/components/schemas/User'
        User:
          title: User
          type: object
          description: ユーザー
          properties:
            id:
              type: integer
              example: 1
            email:
              type: string
              example: abc@abc.com
            username:
              type: string
              example: 山本 太郎
            nickname:
              type: string
              example: たろう
            bio:
              type: string
              example: 自己紹介文が入ります。自己紹介文が入ります。
            firebase_id:
              type: string
              example: 0123456789
          required:
            - id
            - email
            - username
            - nickname
        Users:
          title: User List
          type: object
          description: User List
          properties:
            # total_pages:
            #   type: integer
            #   example: 2
            users:
              type: array
              items:
                $ref: '#/components/schemas/User'
        UserAfterCreate:
          title: UserAfterCreate
          type: object
          description: UserAfterCreate
          properties:
            user:
              allOf:
                - type: object
                - $ref: '#/components/schemas/User'
            code_error_signup:
              type: string
              example: 2J8ASBK9SJHBJUIOHU8976SASAS9SA7AS
        NewUser:
          title: NewUser
          type: object
          description: 新規ユーザー
          properties:
            id:
              type: integer
              example: 1
            email:
              type: string
              example: abc@abc.com
            username:
              type: string
              example: 山田 二郎
            nickname:
              type: string
              example: じろう
            bio:
              type: string
              example: 自己紹介文が入ります。自己紹介文が入ります。
            firebase_id:
              type: string
              example: 0123456789
        Task:
          title: Task
          type: object
          description: タスク
          properties:
            id:
              type: integer
              example: 1
            title:
              type: string
              example: タスクのタイトルが入ります。タスクのタイトルが入ります。
            content:
              # text
              type: string
              example: タスクの内容が入ります。タスクの内容が入ります。
            user_id:
              # bigint
              type: integer
              example: 1
            status:
              type: integer
              example: 0
            start_date:
              type: string
              example: 2022-01-01
            end_date:
              type: string
              example: 2022-12-31
          required:
            - id
            - title
            - user_id
            - status
            - start_date
            - end_date
        Tasks:
          title: Task List
          type: object
          description: Task List
          properties:
            # total_pages:
            #   type: integer
            #   example: 2
            tasks:
              type: array
              items:
                $ref: '#/components/schemas/Task'
        Like:
          title: Like
          type: object
          description: いいね
          properties:
            id:
              type: integer
              example: 1
            task_id:
              # bigint
              type: integer
              example: 1
            user_id:
              # bigint
              type: integer
              example: 1
          required:
            - id
            - task_id
            - user_id
        Likes:
          title: Like List
          type: object
          description: Like List
          properties:
            # total_pages:
            #   type: integer
            #   example: 2
            likes:
              type: array
              items:
                $ref: '#/components/schemas/Like'
        Relationship:
          title: Relationship
          type: object
          description: フォロー
          properties:
            id:
              type: integer
              example: 1
            following_id:
              # bigint
              type: integer
              example: 1
            follower_id:
              # bigint
              type: integer
              example: 1
          required:
            - id
            - following_id
            - follower_id
        Relationships:
          title: Relationship List
          type: object
          description: Relationship List
          properties:
            # total_pages:
            #   type: integer
            #   example: 2
            relationships:
              type: array
              items:
                $ref: '#/components/schemas/Relationship'
        Notification:
          title: Notification
          type: object
          description: 通知
          properties:
            id:
              type: integer
              example: 1
            task_id:
              # bigint
              type: integer
              example: 1
            action:
              type: string
              example: like
            checked:
              # bigint
              type: boolean
              example: false
            visitor_id:
              # bigint
              type: integer
              example: 1
            visited_id:
              # bigint
              type: integer
              example: 2
          required:
            - id
            - following_id
            - follower_id
        Notifications:
          title: Notification List
          type: object
          description: Notification List
          properties:
            # total_pages:
            #   type: integer
            #   example: 2
            notifications:
              type: array
              items:
                $ref: '#/components/schemas/Notification'
    © 2022, rubicon44TechBlog All rights reserved.