Конечные точки облака Google не поддерживают файл - PullRequest
1 голос
/ 16 марта 2020

Я разработал свой бэкэнд, используя Spring boot.

Я интегрирую облачные конечные точки, но у меня много ошибок, потому что я могу загрузить файл (apk, images) с некоторыми из моих API.

Вот мой файл swagger:

 swagger: '2.0'
info:
    description: 'Api Documentation'
    version: '1.0.0'
    title: 'Api Documentation for apk micro service'
    termsOfService: 'urn:tos'
    contact: {}
    license:
        name: 'Apache 2.0'
        url: 'http://www.apache.org/licenses/LICENSE-2.0'
host: "mapk.api.gara.store"
basePath: /
tags:
    -
        name: apk-service-controller
        description: 'Apk Service Controller'
    -
        name: category-controller
        description: 'Category Controller'

schemes:
# Uncomment the next line if you configure SSL for this API.
# - "https"
  - "http"
paths:
    /api/apk/:
        post:
            tags: [apk-service-controller]
            summary: create
            operationId: createUsingPOST
            consumes: [application/json]
            produces: [application/json]
            parameters: [{in: body, name: apkDto, description: apkDto, required: true, schema: {$ref: '#/definitions/ApkDto'}}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
        put:
            tags: [apk-service-controller]
            summary: update
            operationId: updateUsingPUT
            consumes: [application/json]
            produces: [application/json]
            parameters: [{in: body, name: apkDto, description: apkDto, required: true, schema: {$ref: '#/definitions/ApkDto'}}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/activateapkversion:
        post:
            tags: [apk-service-controller]
            summary: activateApkVersion
            operationId: activateApkVersionUsingPOST
            consumes: [application/json]
            produces: ['*/*']
            parameters: [{name: apkId, in: query, description: apkId, required: true, type: integer, format: int64}, {name: codeVersion, in: query, description: codeVersion, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/addapk:
        post:
            tags: [apk-service-controller]
            summary: addApkFile
            operationId: addApkFileUsingPOST
            consumes: [multipart/form-data]
            produces: ['*/*']
            parameters: [{name: file, in: formData, description: file, required: true, type: file}, {name: apkId, in: query, description: apkId, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/ApkVersion'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/addorupdatecover:
        post:
            tags: [apk-service-controller]
            summary: uploadOrUpdateCoverImage
            operationId: uploadOrUpdateCoverImageUsingPOST
            consumes: [multipart/form-data]
            produces: ['*/*']
            parameters: [{name: file, in: formData, description: file, required: true, type: file}, {name: apkId, in: query, description: apkId, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/addorupdateicon:
        post:
            tags: [apk-service-controller]
            summary: uploadOrUpdateIconImage
            operationId: uploadOrUpdateIconImageUsingPOST
            consumes: [multipart/form-data]
            produces: ['*/*']
            parameters: [{name: file, in: formData, description: file, required: true, type: file}, {name: apkId, in: query, description: apkId, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/addscreenshots:
        post:
            tags: [apk-service-controller]
            summary: addOrUpdateScreenShot
            operationId: addOrUpdateScreenShotUsingPOST
            consumes: [multipart/form-data]
            produces: ['*/*']
            parameters: [{name: file, in: formData, description: file, required: true, type: file}, {name: apkId, in: query, description: apkId, required: true, type: integer, format: int64}, {name: index, in: query, description: index, required: true, type: integer, format: int32}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/category/:
        get:
            tags: [category-controller]
            summary: getAllCategories
            operationId: getAllCategoriesUsingGET
            produces: [application/json]
            responses: {'200': {description: OK, schema: {type: array, items: {$ref: '#/definitions/Category'}}}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
            security:
              - api_key: []
        post:
            tags: [category-controller]
            summary: createCategory
            operationId: createCategoryUsingPOST
            consumes: [application/json]
            produces: [application/json]
            parameters: [{name: categoryname, in: query, description: categoryname, required: true, type: string}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Category'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/category/addsubcategory:
        post:
            tags: [category-controller]
            summary: addSubCategory
            operationId: addSubCategoryUsingPOST
            consumes: [application/json]
            produces: ['*/*']
            parameters: [{name: categoryId, in: query, description: categoryId, required: true, type: integer, format: int64}, {name: subcategory, in: query, description: subcategory, required: true, type: string}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Category'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    /api/apk/category/removesubcategory:
        post:
            tags: [category-controller]
            summary: removeSubCategory
            operationId: removeSubCategoryUsingPOST
            consumes: [application/json]
            produces: ['*/*']
            parameters: [{name: categoryId, in: query, description: categoryId, required: true, type: integer, format: int64}, {name: subCategoryId, in: query, description: subCategoryId, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Category'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    '/api/apk/category/{categoryId}':
        delete:
            tags: [category-controller]
            summary: delete
            operationId: deleteUsingDELETE_1
            produces: ['*/*']
            parameters: [{name: categoryId, in: path, description: categoryId, required: true, type: integer, format: int64}]
            responses: {'200': {description: OK}, '204': {description: 'No Content'}, '401': {description: Unauthorized}, '403': {description: Forbidden}}
            security:
              - api_key: []
    '/api/apk/category/{id}':
        get:
            tags: [category-controller]
            summary: getCategoyById
            operationId: getCategoyByIdUsingGET
            produces: ['*/*']
            parameters: [{name: id, in: path, description: id, required: true, type: integer, format: int64}]
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Category'}}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
            security:
              - api_key: []
    '/api/apk/company/{companyId}':
        get:
            tags: [apk-service-controller]
            summary: getAllWebtoonByCompany
            operationId: getAllWebtoonByCompanyUsingGET
            produces: ['*/*']
            parameters: [{name: companyId, in: query, description: companyId, required: false, type: integer, format: int64}]
            responses: {'200': {description: OK, schema: {type: array, items: {$ref: '#/definitions/Apk'}}}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
            security:
              - api_key: []
    /api/apk/reviewandrated:
        post:
            tags: [apk-service-controller]
            summary: addAndUpdateReviewAndNote
            operationId: addAndUpdateReviewAndNoteUsingPOST
            consumes: [application/json]
            produces: [application/json]
            parameters: [{in: body, name: apkReviewDto, description: apkReviewDto, required: true, schema: {$ref: '#/definitions/ApkReviewDto'}}]
            security:
              - api_key: []
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '201': {description: Created}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
    '/api/apk/{id}':
        get:
            tags: [apk-service-controller]
            summary: getApkById
            operationId: getApkByIdUsingGET
            produces: ['*/*']
            parameters: [{name: id, in: path, description: id, required: true, type: integer, format: int64}]
            security:
              - api_key: []            
            responses: {'200': {description: OK, schema: {$ref: '#/definitions/Apk'}}, '401': {description: Unauthorized}, '403': {description: Forbidden}, '404': {description: 'Not Found'}}
        delete:
            tags: [apk-service-controller]
            summary: delete
            operationId: deleteUsingDELETE
            produces: ['*/*']
            parameters: [{name: id, in: path, description: id, required: true, type: integer, format: int64}]
            security:
              - api_key: []
            responses: {'200': {description: OK}, '204': {description: 'No Content'}, '401': {description: Unauthorized}, '403': {description: Forbidden}}

    "/auth/info/googlejwt":
        get:
            description: "Returns the requests' authentication information."
            operationId: "auth_info_google_jwt"
            produces:
                - "application/json"
            responses:
                200:
                  description: "Authenication info."
                  schema:
                    $ref: "#/definitions/authInfoResponse"
            security:
              - api_key: []
                google_jwt: []
    "/auth/info/googleidtoken":
        get:
            description: "Returns the requests' authentication information."
            operationId: "authInfoGoogleIdToken"
            produces:
                - "application/json"
            responses:
                200:
                  description: "Authenication info."
                  schema:
                    $ref: "#/definitions/authInfoResponse"
            security:
              - api_key: []
                google_id_token: []

definitions:
    Apk:
        type: object
        properties:
            apkDownloadUrl: {type: string}
            apkName: {type: string}
            apkPath: {type: string}
            category: {$ref: '#/definitions/Category'}
            changes: {type: string}
            companyId: {type: integer, format: int64}
            containsAds: {type: boolean}
            coverDownloadUrl: {type: string}
            coverPath: {type: string}
            dependencies: {type: array, items: {type: string}}
            description: {type: string}
            displayName: {type: string}
            iconDownloadUrl: {type: string}
            iconPath: {type: string}
            id: {type: integer, format: int64}
            installs: {type: integer, format: int64}
            isFree: {type: boolean}
            listOfapkVersion: {type: array, items: {$ref: '#/definitions/ApkVersion'}}
            maxSdkVersion: {type: string}
            minSdkVersion: {type: string}
            packageName: {type: string}
            permissions: {type: array, items: {type: string}}
            price: {type: number}
            rating: {$ref: '#/definitions/Rating'}
            repositoryGeneratedId: {type: string}
            screenshotList: {type: array, items: {type: string}}
            shortDescription: {type: string}
            size: {type: integer, format: int64}
            status: {type: string, enum: [INITIATED, PUBLISHED, VALIDATION_IN_PROGRESS, REJECTED]}
            subCategory: {$ref: '#/definitions/SubCategory'}
            targetSdkVersion: {type: string}
            userReview: {type: array, items: {$ref: '#/definitions/Review'}}
            versionCode: {type: integer, format: int64}
            versionName: {type: string}
            videoUrl: {type: string}
        title: Apk
    ApkDto:
        type: object
        properties:
            allMandatoryFieldsFilledForCreation: {type: boolean}
            apkId: {type: integer, format: int64}
            categoryId: {type: integer, format: int64}
            companyId: {type: integer, format: int64}
            description: {type: string}
            displayName: {type: string}
            isFree: {type: boolean}
            price: {type: number}
            shortDescription: {type: string}
            subCategoryId: {type: integer, format: int64}
        title: ApkDto
    ApkReviewDto:
        type: object
        properties:
            apkId: {type: integer, format: int64}
            appUserId: {type: integer, format: int64}
            minimumFielsRequiredSet: {type: boolean}
            reviewComment: {type: string}
            reviewId: {type: integer, format: int64}
            stars: {type: integer, format: int32}
        title: ApkReviewDto
    ApkVersion:
        type: object
        properties:
            artifactId: {type: string}
            compileSdkVersion: {type: string}
            compileSdkVersionCodename: {type: string}
            configForSplit: {type: string}
            dependencies: {type: array, items: {type: string}}
            downloadPath: {type: string}
            featureSplit: {type: boolean}
            groupId: {type: string}
            id: {type: integer, format: int64}
            installLocation: {type: string}
            isolatedSplits: {type: boolean}
            label: {type: string}
            maxSdkVersion: {type: string}
            minSdkVersion: {type: string}
            name: {type: string}
            packageName: {type: string}
            path: {type: string}
            permissions: {type: array, items: {type: string}}
            platformBuildVersionCode: {type: string}
            revisionCode: {type: integer, format: int64}
            sharedUserId: {type: string}
            sharedUserLabel: {type: string}
            size: {type: integer, format: int64}
            split: {type: string}
            splitRequired: {type: boolean}
            targetSdkVersion: {type: string}
            usesFeatures: {type: array, items: {type: string}}
            versionCode: {type: integer, format: int64}
            versionName: {type: string}
        title: ApkVersion
    Category:
        type: object
        properties:
            id: {type: integer, format: int64}
            name: {type: string}
            subCategoryList: {type: array, items: {$ref: '#/definitions/SubCategory'}}
        title: Category
    Rating:
        type: object
        properties:
            average: {type: number, format: float}
            ratingId: {type: integer, format: int64}
            stars: {type: object, additionalProperties: {type: integer, format: int32}}
            starsByUserId: {type: object, additionalProperties: {type: integer, format: int32}}
        title: Rating
    Review:
        type: object
        properties:
            appUserId: {type: integer, format: int64}
            comment: {type: string}
            commentDate: {type: string, format: date-time}
            id: {type: integer, format: int64}
            stars: {type: integer, format: int32}
        title: Review
    SubCategory:
        type: object
        properties:
            id: {type: integer, format: int64}
            name: {type: string}
        title: SubCategory

securityDefinitions:
  # This section configures basic authentication with an API key.
  api_key:
    type: "apiKey"
    name: "key"
    in: "query"
  # This section configures authentication using Google API Service Accounts
  # to sign a json web token. This is mostly used for server-to-server
  # communication.
  google_jwt:
    authorizationUrl: ""
    flow: "implicit"
    type: "oauth2"
    # This must match the 'iss' field in the JWT.
    x-google-issuer: "jwt-client.endpoints.sample.google.com"
    # Update this with your service account's email address.
    x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/jwk/YOUR-SERVICE-ACCOUNT-EMAIL"
    # This must match the "aud" field in the JWT. You can add multiple
    # audiences to accept JWTs from multiple clients.
    x-google-audiences: "echo.endpoints.sample.google.com"
  # This section configures authentication using Google OAuth2 ID Tokens.
  # ID Tokens can be obtained using OAuth2 clients, and can be used to access
  # your API on behalf of a particular user.
  google_id_token:
    authorizationUrl: ""
    flow: "implicit"
    type: "oauth2"
    x-google-issuer: "https://accounts.google.com"
    x-google-jwks_uri: "https://www.googleapis.com/oauth2/v3/certs"
    # Your OAuth2 client's Client ID must be added here. You can add
    # multiple client IDs to accept tokens from multiple clients.
    x-google-audiences: "YOUR-CLIENT-ID"

Я получил следующие ошибки с моей командой развертывания gcloud --verbosity=debug endpoints services deploy openapi.yaml:

INFO: Refreshing access_token
DEBUG: Running [gcloud.endpoints.services.deploy] with arguments: [--verbosity: "debug", SERVICE_CONFIG_FILE:1: "[u'openapi.yaml']"]
INFO: No JSON detected in service config. Trying YAML...
DEBUG: (gcloud.endpoints.services.deploy) INVALID_ARGUMENT: Cannot convert to service config.
'location: "unknown location"
kind: ERROR
message: "http: repeated message field \'google.protobuf.Struct.fields\' referred to by message \'AddApkFileUsingPOSTRequest\' cannot be mapped as an HTTP parameter."

 location: "unknown location"
kind: ERROR
message: "http: cyclic message field \'google.protobuf.Struct.FieldsEntry.value\' referred to by message \'AddApkFileUsingPOSTRequest\' in method \'method 1.mapk_api_gara_store.AddApkFileUsingPOST\' cannot be mapped as an HTTP parameter."

 location: "unknown location"
kind: ERROR
message: "http: cyclic message field \'google.protobuf.ListValue.values\' referred to by message \'AddApkFileUsingPOSTRequest\' in method \'method 1.mapk_api_gara_store.AddApkFileUsingPOST\' cannot be mapped as an HTTP parameter."

location: "unknown location"
kind: ERROR
message: "http: repeated message field \'google.protobuf.Struct.fields\' referred to by message \'AddOrUpdateScreenShotUsingPOSTRequest\' cannot be mapped as an HTTP parameter."

 location: "unknown location"
kind: ERROR
message: "http: cyclic message field \'google.protobuf.Struct.FieldsEntry.value\' referred to by message \'AddOrUpdateScreenShotUsingPOSTRequest\' in method \'method 1.mapk_api_gara_store.AddOrUpdateScreenShotUsingPOST\' cannot be mapped as an HTTP parameter."

Traceback (most recent call last):
  File "/usr/lib64/google-cloud-sdk/lib/googlecloudsdk/calliope/cli.py", line 984, in Execute
    resources = calliope_command.Run(cli=self, args=args)
  File "/usr/lib64/google-cloud-sdk/lib/googlecloudsdk/calliope/backend.py", line 807, in Run
    resources = command_instance.Run(args)
  File "/usr/lib64/google-cloud-sdk/lib/surface/endpoints/services/deploy.py", line 356, in Run
    validate_only=self.validate_only)
  File "/usr/lib64/google-cloud-sdk/lib/googlecloudsdk/api_lib/endpoints/services_util.py", line 333, in PushMultipleServiceConfigFiles
    api_response = client.services_configs.Submit(submit_request)
  File "/usr/lib64/google-cloud-sdk/lib/googlecloudsdk/third_party/apis/servicemanagement/v1/servicemanagement_v1_client.py", line 273, in Submit
    config, request, global_params=global_params)
  File "/usr/lib64/google-cloud-sdk/lib/third_party/apitools/base/py/base_api.py", line 731, in _RunMethod
    return self.ProcessHttpResponse(method_config, http_response, request)
  File "/usr/lib64/google-cloud-sdk/lib/third_party/apitools/base/py/base_api.py", line 737, in ProcessHttpResponse
    self.__ProcessHttpResponse(method_config, http_response, request))
  File "/usr/lib64/google-cloud-sdk/lib/third_party/apitools/base/py/base_api.py", line 604, in __ProcessHttpResponse
    http_response, method_config=method_config, request=request)
HttpBadRequestError: HttpError accessing <https://servicemanagement.googleapis.com/v1/services/mapk.api.gara.store/configs:submit?alt=json>: response: <{'status': '400', 'content-length': '3538', 'x-xss-protection': '0', 'x-content-type-options': 'nosniff', 'transfer-encoding': 'chunked', 'vary': 'Origin, X-Origin, Referer', 'server': 'ESF', '-content-encoding': 'gzip', 'cache-control': 'private', 'date': 'Tue, 17 Mar 2020 20:58:29 GMT', 'x-frame-options': 'SAMEORIGIN', 'alt-svc': 'quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000', 'content-type': 'application/json; charset=UTF-8'}>, content <{
  "error": {
    "code": 400,
    "message": "Cannot convert to service config.\n'location: \"unknown location\"\nkind: ERROR\nmessage: \"http: repeated message field \\'google.protobuf.Struct.fields\\' referred to by message \\'AddApkFileUsingPOSTRequest\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.Struct.FieldsEntry.value\\' referred to by message \\'AddApkFileUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.AddApkFileUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.ListValue.values\\' referred to by message \\'AddApkFileUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.AddApkFileUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: repeated message field \\'google.protobuf.Struct.fields\\' referred to by message \\'UploadOrUpdateCoverImageUsingPOSTRequest\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.Struct.FieldsEntry.value\\' referred to by message \\'UploadOrUpdateCoverImageUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.UploadOrUpdateCoverImageUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.ListValue.values\\' referred to by message \\'UploadOrUpdateCoverImageUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.UploadOrUpdateCoverImageUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: repeated message field \\'google.protobuf.Struct.fields\\' referred to by message \\'UploadOrUpdateIconImageUsingPOSTRequest\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.Struct.FieldsEntry.value\\' referred to by message \\'UploadOrUpdateIconImageUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.UploadOrUpdateIconImageUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.ListValue.values\\' referred to by message \\'UploadOrUpdateIconImageUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.UploadOrUpdateIconImageUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: repeated message field \\'google.protobuf.Struct.fields\\' referred to by message \\'AddOrUpdateScreenShotUsingPOSTRequest\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.Struct.FieldsEntry.value\\' referred to by message \\'AddOrUpdateScreenShotUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.AddOrUpdateScreenShotUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n\n location: \"unknown location\"\nkind: ERROR\nmessage: \"http: cyclic message field \\'google.protobuf.ListValue.values\\' referred to by message \\'AddOrUpdateScreenShotUsingPOSTRequest\\' in method \\'method 1.mapk_api_gara_store.AddOrUpdateScreenShotUsingPOST\\' cannot be mapped as an HTTP parameter.\"\n'",
    "status": "INVALID_ARGUMENT"
  }
}
>
ERROR: (gcloud.endpoints.services.deploy) INVALID_ARGUMENT: Cannot convert to service config.
'location: "unknown location"
kind: ERROR
message: "http: repeated message field \'google.protobuf.Struct.fields\' referred to by message \'AddApkFileUsingPOSTRequest\' cannot be mapped as an HTTP parameter."

 location: "unknown location"
kind: ERROR
message: "http: cyclic message field \'google.protobuf.Struct.FieldsEntry.value\' referred to by message \'AddApkFileUsingPOSTRequest\' in method \'method 1.mapk_api_gara_store.AddApkFileUsingPOST\' cannot be mapped as an HTTP parameter."

Как я могу это сделать? Похоже, что облачные конечные точки не поддерживают файл. Мое приложение на рынке, мне нужно загрузить файл через мои API.

Спасибо

...