https.onCall의 프로토콜 사양

Cloud Functions의 https.onCall 트리거는 요청 및 응답에 특정 형식이 필요한 HTTPS 트리거입니다. 이 섹션에서는 API를 구현하기 위해 클라이언트 SDK에서 사용하는 HTTPS 요청 및 응답 형식의 사양을 설명합니다. 이 정보는 Android, Apple 플랫폼 또는 웹 SDK로 요구사항을 충족할 수 없는 경우에 유용합니다.

요청 형식: 헤더

호출 가능한 트리거 엔드포인트에 대한 HTTP 요청은 다음 헤더가 있는 POST여야 합니다.

  • 필수: Content-Type: application/json
    • 원하는 경우 ; charset=utf-8을 사용할 수 있습니다.
  • 선택사항: Authorization: Bearer <token>
    • 요청한 로그인 사용자의 Firebase Authentication 사용자 ID 토큰입니다. 백엔드에서 이 토큰을 자동으로 확인하고 핸들러의 context에 제공합니다. 토큰이 유효하지 않으면 요청이 거부됩니다.
  • 선택사항: Firebase-Instance-ID-Token: <iid>
    • Firebase 클라이언트 SDK의 FCM 등록 토큰입니다. 문자열이어야 합니다. 이 토큰은 핸들러의 context에 사용할 수 있으며 푸시 알림을 타겟팅하는 데 사용됩니다.
  • 선택사항: X-Firebase-AppCheck: <token>
    • 요청을 보내는 클라이언트 앱에서 제공하는 Firebase 앱 체크 토큰입니다. 백엔드에서 이 토큰을 자동으로 확인하여 디코딩하고 핸들러의 contextappId를 삽입합니다. 토큰을 확인할 수 없으면 요청이 거부됩니다. (SDK 3.14.0 이상에서 사용 가능)

다른 헤더가 포함되어 있으면 아래의 응답 문서의 설명대로 요청이 거부됩니다.

참고: 자바스크립트 클라이언트에서 이러한 요청은 다음과 같은 이유로 CORS OPTIONS 실행 전 요청을 트리거합니다.

  • application/json은 허용되지 않습니다. text/plain 또는 application/x-www-form-urlencoded여야 합니다.
  • Authorization 헤더는 CORS 허용 목록에 있는 요청 헤더가 아닙니다.
  • 다른 헤더도 마찬가지로 허용되지 않습니다.

호출 가능 트리거는 이러한 OPTIONS 요청을 자동으로 처리합니다.

요청 본문

HTTP 요청 본문은 다음 필드가 있는 JSON 객체여야 합니다.

  • 필수: data - 함수에 전달되는 인수입니다. 모든 유효한 JSON 값이 여기에 해당될 수 있습니다. 이 값은 아래에 설명된 직렬화 형식에 따라 자동으로 기본 자바스크립트 유형으로 디코딩됩니다.

요청에 다른 필드가 있는 경우 백엔드는 요청이 잘못된 것으로 간주하여 거부합니다.

응답 형식: 상태 코드

응답 오류에 다양한 HTTP 상태 코드와 문자열 상태 코드를 발생시킬 수 있는 경우는 다음과 같습니다.

  1. client 트리거가 호출되기 전에 HTTP 오류가 발생하면 응답은 클라이언트 함수로 처리되지 않습니다. 예를 들어 클라이언트가 존재하지 않는 함수를 호출하려고 하면 404 Not Found 응답이 발생합니다.

  2. 클라이언트 트리거가 호출되었지만 요청이 잘못된 형식(예: JSON이 아니거나 유효하지 않은 필드가 있거나 data 필드가 누락됨)이면 요청은 400 Bad Request 응답과 함께 거부되고 오류 코드는 INVALID_ARGUMENT입니다.

  3. 요청에 제공된 인증 토큰이 유효하지 않으면 요청은 401 Unauthorized 응답과 함께 거부되고 오류 코드는 UNAUTHENTICATED입니다.

  4. 요청에 제공된 FCM 등록 토큰이 유효하지 않은 경우 정의되지 않은 동작이 발생합니다. 토큰은 FCM으로 푸시 알림을 보낼 때 사용되는 경우를 제외하고 모든 요청에서 확인되지 않습니다.

  5. 호출 가능 트리거를 호출하였지만 처리되지 않은 예외 혹은 프라미스 실패와 함께 오류가 발생하는 경우 요청은 500 Internal Server Error 응답과 함께 거부되며 오류 코드는 INTERNAL입니다. 이렇게 하면 코딩 오류가 실수로 최종 사용자에게 노출되는 것을 방지할 수 있습니다.

  6. 호출 가능 트리거를 호출하고 호출 가능 함수에 제공된 API를 사용하여 명시적 오류 상태가 반환되면 요청이 실패합니다. 반환되는 HTTP 상태 코드는 code.proto에 정의된 바와 같이 HTTP 상태에 대한 오류 상태의 공식 매핑을 기반으로 합니다. 반환되는 특정 오류 코드, 메시지 및 세부정보는 아래 설명대로 응답 본문에 인코딩됩니다. 즉, 함수가 OK 상태와 함께 명시적 오류를 반환하면 응답 상태는 200 OK이지만 error 필드가 응답에 설정됩니다.

  7. 클라이언트 트리거가 성공하면 응답 상태는 200 OK입니다.

응답 형식: 헤더

응답은 다음과 같은 헤더를 포함합니다.

  • Content-Type: application/json
  • 원하는 경우 ; charset=utf-8을 사용할 수 있습니다.

응답 본문

클라이언트 엔드포인트의 응답은 항상 JSON 객체입니다. 적어도 result 또는 error를 포함하며 원하는 경우 다른 필드도 포함할 수 있습니다. 응답이 JSON 객체가 아니거나 data 또는 error를 포함하지 않은 경우 클라이언트 SDK는 요청을 Google 오류 코드 INTERNAL (13)과 함께 실패한 것으로 처리해야 합니다.

  • error - 이 필드가 있으면 HTTP 상태 코드 또는 data 존재 여부에 관계없이 요청이 실패한 것으로 간주됩니다. 이 필드 값은 status, message, details(선택사항) 필드가 있고 오류에 표준 Google Cloud HTTP 매핑 형식을 따르는 JSON 객체여야 합니다. code 필드는 포함되지 않아야 합니다. status 필드가 설정되지 않았거나 유효하지 않은 값이면 클라이언트는 code.proto에 따라 상태를 INTERNAL로 처리해야 합니다. details가 있으면 클라이언트 SDK의 오류에 연결된 모든 사용자 정보에 포함됩니다(해당되는 경우).
    참고: 여기에서 details 필드는 사용자가 제공한 값입니다. Google Status 형식에 있는 것과 같이 proto 유형으로 키가 지정된 값의 목록일 필요는 없습니다.
  • result - 함수에서 반환하는 값입니다. 모든 유효한 JSON 값이 여기에 해당될 수 있습니다. Firebase 함수 SDK는 사용자가 반환한 값을 이 JSON 형식으로 자동 인코딩합니다. 클라이언트 SDK는 아래에 설명된 직렬화 형식에 따라 이러한 매개변수를 기본 형식으로 자동 디코딩합니다.

다른 필드는 있는 경우 무시됩니다.

직렬화

임의 데이터 페이로드의 직렬화 형식은 요청과 응답 모두의 경우에 동일합니다.

일관된 플랫폼을 위해 이러한 항목은 표준 JSON 매핑을 통해 proto3 프로토콜 버퍼의 Any 필드 값과 같은 방식으로 JSON으로 인코딩됩니다. null, int, double 또는 string과 같은 간단한 유형의 값은 직접 인코딩되지만 명시적 유형을 포함하지 않습니다. 따라서 floatdouble은 동일한 방식으로 인코딩되며 호출 상대방에서 어떤 것이 수신되는지 알지 못할 수 있습니다. JSON에서 기본이 아닌 유형의 경우, 유형이 지정된 proto3 인코딩이 값에 사용됩니다. 자세한 내용은 JSON 인코딩 문서를 참조하세요.

허용되는 유형은 다음과 같습니다.

  • null - null
  • int(부호 있음 또는 부호 없음, 최대 32비트) - 예: 3 또는 -30
  • float - 예: 3.14
  • double - 예: 3.14
  • double - 예: true 또는 false
  • string - 예: "hello world"
  • map<string, any=""> - 예: {"x": 3}</string,>
  • list - 예: [1, 2, 3]
  • long(부호 있음 또는 부호 없음, 최대 64비트) - [자세한 내용은 아래 참조]

floatdoubleNaNInfinity 값은 지원되지 않습니다.

long은 JSON에서 일반적으로 허용되지 않는 특수 유형이지만 proto3 사양에서는 취급됩니다. 예를 들어 다음과 같이 인코딩됩니다.

long

{
    '@type': 'type.googleapis.com/google.protobuf.Int64Value',
    'value': '-123456789123456'
}

부호가 없는 long

{
    '@type': 'type.googleapis.com/google.protobuf.UInt64Value',
    'value': '123456789123456'
}

일반적으로 @type 키는 예약된 것으로 간주되어야 하며 전달되는 맵에 사용되지 않아야 합니다.

그 이유는 유형이 단순 유형에 지정되지 않아서 전달된 후에 일부 값의 유형이 바뀌기 때문입니다. 예를 들어 전달된 floatdouble이 되며 shortint가 되는 식입니다. Android에서는 목록 값으로 ListJSONArray가 모두 지원됩니다. 이 경우 JSONArray를 전달하면 List가 생성됩니다.

알 수 없는 유형의 @type 필드가 있는 맵이 역직렬화되면 맵으로 남습니다. 이를 통해 개발자는 기존 클라이언트의 손상 없이 새로운 유형의 필드를 반환 값에 추가할 수 있습니다.

코드 샘플

이 섹션의 샘플은 다음을 인코딩하는 방법을 보여줍니다.

  • Swift의 callable.call 예제
  • 호출 성공 응답
  • 호출 실패 응답

Swift의 Callable.call 예제 인코딩

callable.call([
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23,
    "aLong": -123456789123456 as Int64
])

요청 헤더:

Method: POST
Content-Type: application/json; charset=utf-8
Authorization: Bearer some-auth-token
Firebase-Instance-ID-Token: some-iid-token

요청 본문:

{
    "data": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23,
        "aLong": {
            "@type": "type.googleapis.com/google.protobuf.Int64Value",
            "value": "-123456789123456"
        }
    }
}

응답 인코딩

return {
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23
};

성공 응답 헤더:

200 OK
Content-Type: application/json; charset=utf-8

성공 응답 본문:

{
    "response": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23
    }
}

실패 응답 인코딩

throw new HttpsError("unauthenticated", "Request had invalid credentials.", {
  "some-key": "some-value"
});

실패 응답 헤더:

401 UNAUTHENTICATED
Content-Type: application/json; charset=utf-8

실패 응답 본문:

{
    "error": {
        "message": "Request had invalid credentials.",
        "status": "UNAUTHENTICATED",
        "details": {
            "some-key": "some-value"
        }
    }
}