File
Blob: src/workerd/api/r2-rpc.h
| 1 | // Copyright (c) 2017-2022 Cloudflare, Inc. |
| 2 | // Licensed under the Apache 2.0 license found in the LICENSE file or at: |
| 3 | // https://opensource.org/licenses/Apache-2.0 |
| 4 | |
| 5 | #pragma once |
| 6 | |
| 7 | #include <workerd/api/blob.h> |
| 8 | #include <workerd/jsg/jsg.h> |
| 9 | |
| 10 | namespace kj { |
| 11 | class HttpClient; |
| 12 | } |
| 13 | |
| 14 | namespace workerd::api { |
| 15 | |
| 16 | class ReadableStreamSource; |
| 17 | class ReadableStream; |
| 18 | |
| 19 | // NOTE: We don't currently actually use this as a structured object (hence the `kj::Own<R2Error>` |
| 20 | // that we see pop up). |
| 21 | // TODO(soon): Switch to structured objects and use jsg::Ref<R2Error> instead of kj::Own<R2Error> |
| 22 | // to maintain ownership. |
| 23 | class R2Error: public jsg::Object { |
| 24 | public: |
| 25 | R2Error(uint v4Code, kj::String message): v4Code(v4Code), message(kj::mv(message)) {} |
| 26 | |
| 27 | constexpr kj::StringPtr getName() const { |
| 28 | return "R2Error"_kj; |
| 29 | } |
| 30 | uint getV4Code() const { |
| 31 | return v4Code; |
| 32 | } |
| 33 | kj::StringPtr getMessage() const { |
| 34 | return message; |
| 35 | } |
| 36 | kj::StringPtr getAction() const { |
| 37 | return KJ_ASSERT_NONNULL(action); |
| 38 | } |
| 39 | jsg::JsValue getStack(jsg::Lock& js); |
| 40 | |
| 41 | JSG_RESOURCE_TYPE(R2Error) { |
| 42 | JSG_INHERIT_INTRINSIC(v8::kErrorPrototype); |
| 43 | |
| 44 | JSG_READONLY_INSTANCE_PROPERTY(name, getName); |
| 45 | JSG_READONLY_INSTANCE_PROPERTY(code, getV4Code); |
| 46 | JSG_READONLY_INSTANCE_PROPERTY(message, getMessage); |
| 47 | JSG_READONLY_INSTANCE_PROPERTY(action, getAction); |
| 48 | |
| 49 | JSG_READONLY_INSTANCE_PROPERTY(stack, getStack); |
| 50 | // See getStack in dom-exception.h |
| 51 | |
| 52 | JSG_TS_ROOT(); |
| 53 | } |
| 54 | |
| 55 | private: |
| 56 | uint v4Code; |
| 57 | kj::String message; |
| 58 | kj::Maybe<kj::String> action; |
| 59 | // Initialized when thrown. |
| 60 | |
| 61 | kj::Maybe<v8::Global<v8::Object>> errorForStack; |
| 62 | // See dom-exception.h. |
| 63 | |
| 64 | friend struct R2Result; |
| 65 | }; |
| 66 | |
| 67 | using R2PutValue = kj::OneOf<jsg::Ref<ReadableStream>, |
| 68 | kj::Array<kj::byte>, |
| 69 | jsg::NonCoercible<kj::String>, |
| 70 | jsg::Ref<Blob>>; |
| 71 | |
| 72 | struct R2Result { |
| 73 | uint httpStatus; |
| 74 | |
| 75 | // Non-null if httpStatus >= 400. |
| 76 | kj::Maybe<kj::Own<R2Error>> toThrow; |
| 77 | |
| 78 | kj::Maybe<kj::Array<char>> metadataPayload; |
| 79 | |
| 80 | kj::Maybe<kj::Own<workerd::api::ReadableStreamSource>> stream; |
| 81 | |
| 82 | bool objectNotFound() { |
| 83 | return httpStatus == 404 && v4ErrorCode() == 10007; |
| 84 | } |
| 85 | |
| 86 | bool preconditionFailed() { |
| 87 | return httpStatus == 412 && (v4ErrorCode() == 10031 || v4ErrorCode() == 10032); |
| 88 | } |
| 89 | |
| 90 | bool success() { |
| 91 | return httpStatus >= 200 && httpStatus < 400; |
| 92 | } |
| 93 | |
| 94 | kj::Maybe<uint> v4ErrorCode(); |
| 95 | kj::Maybe<kj::String> getR2ErrorMessage(); |
| 96 | void throwIfError(kj::StringPtr action, const jsg::TypeHandler<jsg::Ref<R2Error>>& errorType); |
| 97 | }; |
| 98 | |
| 99 | kj::Promise<R2Result> doR2HTTPGetRequest(kj::Own<kj::HttpClient> client, |
| 100 | kj::String metadataPayload, |
| 101 | kj::ArrayPtr<kj::StringPtr> path, |
| 102 | kj::Maybe<kj::StringPtr> jwt, |
| 103 | CompatibilityFlags::Reader flags); |
| 104 | |
| 105 | kj::Promise<R2Result> doR2HTTPPutRequest(kj::Own<kj::HttpClient> client, |
| 106 | kj::Maybe<R2PutValue> value, |
| 107 | kj::Maybe<uint64_t> streamSize, |
| 108 | // Deprecated. For internal beta API only. |
| 109 | kj::String metadataPayload, |
| 110 | kj::ArrayPtr<kj::StringPtr> path, |
| 111 | kj::Maybe<kj::StringPtr> jwt); |
| 112 | |
| 113 | } // namespace workerd::api |