files.com 1.1.813 → 1.1.815

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/_VERSION +1 -1
  3. data/doc/Files/APIConnectionError.html +1 -1
  4. data/doc/Files/APIError.html +1 -1
  5. data/doc/Files/AccountAlreadyExistsError.html +1 -1
  6. data/doc/Files/AccountLineItem.html +1 -1
  7. data/doc/Files/AccountOverdueError.html +1 -1
  8. data/doc/Files/Action.html +1 -1
  9. data/doc/Files/ActionLog.html +1 -1
  10. data/doc/Files/ActionNotificationExport.html +1 -1
  11. data/doc/Files/ActionNotificationExportResult.html +1 -1
  12. data/doc/Files/AdditionalAuthenticationRequiredError.html +1 -1
  13. data/doc/Files/AgentNode.html +1 -1
  14. data/doc/Files/AgentNodeConnection.html +1 -1
  15. data/doc/Files/AgentNodeInstance.html +1 -1
  16. data/doc/Files/AgentPushUpdate.html +1 -1
  17. data/doc/Files/AgentPushUpdateBlockedError.html +1 -1
  18. data/doc/Files/AgentUnavailableError.html +1 -1
  19. data/doc/Files/AgentUpgradeRequiredError.html +1 -1
  20. data/doc/Files/AiAssistantPersonality.html +1 -1
  21. data/doc/Files/AiTask.html +1 -1
  22. data/doc/Files/AiTaskCannotBeRunManuallyError.html +1 -1
  23. data/doc/Files/AlreadyCompletedError.html +1 -1
  24. data/doc/Files/Api.html +20 -13
  25. data/doc/Files/ApiClient/RequestLogContext.html +29 -29
  26. data/doc/Files/ApiClient/TransferSettings.html +721 -0
  27. data/doc/Files/ApiClient.html +756 -204
  28. data/doc/Files/ApiKey.html +1 -1
  29. data/doc/Files/ApiKeyIsDisabledError.html +1 -1
  30. data/doc/Files/ApiKeyIsPathRestrictedError.html +1 -1
  31. data/doc/Files/ApiKeyNotFoundError.html +1 -1
  32. data/doc/Files/ApiKeyOnlyForDesktopAppError.html +1 -1
  33. data/doc/Files/ApiKeyOnlyForFileOperationsError.html +1 -1
  34. data/doc/Files/ApiKeyOnlyForMobileAppError.html +1 -1
  35. data/doc/Files/ApiKeyOnlyForOfficeIntegrationError.html +1 -1
  36. data/doc/Files/ApiKeySessionsNotSupportedError.html +1 -1
  37. data/doc/Files/ApiRequestLog.html +1 -1
  38. data/doc/Files/App.html +1 -1
  39. data/doc/Files/As2IncomingMessage.html +1 -1
  40. data/doc/Files/As2OutgoingMessage.html +1 -1
  41. data/doc/Files/As2Partner.html +1 -1
  42. data/doc/Files/As2Station.html +1 -1
  43. data/doc/Files/AttachmentTooLargeError.html +1 -1
  44. data/doc/Files/AuthenticationError.html +1 -1
  45. data/doc/Files/AuthenticationRequiredError.html +1 -1
  46. data/doc/Files/Auto.html +1 -1
  47. data/doc/Files/Automation.html +1 -1
  48. data/doc/Files/AutomationAuthoringSchema.html +1 -1
  49. data/doc/Files/AutomationCannotBeRunManuallyError.html +1 -1
  50. data/doc/Files/AutomationExecutionNode.html +1 -1
  51. data/doc/Files/AutomationLog.html +1 -1
  52. data/doc/Files/AutomationRun.html +1 -1
  53. data/doc/Files/AutomationsUnavailableError.html +1 -1
  54. data/doc/Files/BadRequestError.html +1 -1
  55. data/doc/Files/BandwidthSnapshot.html +1 -1
  56. data/doc/Files/Behavior.html +1 -1
  57. data/doc/Files/BehaviorNotAllowedOnRemoteServerError.html +1 -1
  58. data/doc/Files/BillingInformationHiddenError.html +1 -1
  59. data/doc/Files/BillingPermissionRequiredError.html +1 -1
  60. data/doc/Files/BufferedUploadDisabledForThisDestinationError.html +1 -1
  61. data/doc/Files/Bundle.html +1 -1
  62. data/doc/Files/BundleAction.html +1 -1
  63. data/doc/Files/BundleDownload.html +1 -1
  64. data/doc/Files/BundleMaximumUsesReachedError.html +1 -1
  65. data/doc/Files/BundleNotification.html +1 -1
  66. data/doc/Files/BundleOnlyAllowsPreviewsError.html +1 -1
  67. data/doc/Files/BundleOperationRequiresSubfolderError.html +1 -1
  68. data/doc/Files/BundlePath.html +1 -1
  69. data/doc/Files/BundlePathNotFoundError.html +1 -1
  70. data/doc/Files/BundlePermissionRequiredError.html +1 -1
  71. data/doc/Files/BundleRecipient.html +1 -1
  72. data/doc/Files/BundleRegistration.html +1 -1
  73. data/doc/Files/BundleRegistrationCodeFailedError.html +1 -1
  74. data/doc/Files/BundleRegistrationNotFoundError.html +1 -1
  75. data/doc/Files/CannotAdministerHigherLevelUserError.html +1 -1
  76. data/doc/Files/CannotDownloadDirectoryError.html +1 -1
  77. data/doc/Files/CannotLoginWhileUsingKeyError.html +1 -1
  78. data/doc/Files/CantActForOtherUserError.html +1 -1
  79. data/doc/Files/CantMoveWithMultipleLocationsError.html +1 -1
  80. data/doc/Files/ChatMessage.html +1 -1
  81. data/doc/Files/ChatSession.html +1 -1
  82. data/doc/Files/ChildSiteManagementPolicy.html +1 -1
  83. data/doc/Files/Clickwrap.html +1 -1
  84. data/doc/Files/CodeNotFoundError.html +1 -1
  85. data/doc/Files/ConfigurationLockedPathError.html +1 -1
  86. data/doc/Files/ContactAdminForPasswordChangeHelpError.html +1 -1
  87. data/doc/Files/CouldNotCreateParentError.html +1 -1
  88. data/doc/Files/CustomDomain.html +1 -1
  89. data/doc/Files/DatetimeParseError.html +1 -1
  90. data/doc/Files/DesktopConfigurationProfile.html +1 -1
  91. data/doc/Files/DestinationExistsError.html +1 -1
  92. data/doc/Files/DestinationFolderLimitedError.html +1 -1
  93. data/doc/Files/DestinationParentConflictError.html +1 -1
  94. data/doc/Files/DestinationParentDoesNotExistError.html +1 -1
  95. data/doc/Files/DestinationSameError.html +1 -1
  96. data/doc/Files/DestinationSiteMismatchError.html +1 -1
  97. data/doc/Files/DirectConnectionInfo.html +1 -1
  98. data/doc/Files/DnsRecord.html +1 -1
  99. data/doc/Files/DoesNotSupportSortingError.html +1 -1
  100. data/doc/Files/DuplicateShareRecipientError.html +1 -1
  101. data/doc/Files/EmailIncomingMessage.html +1 -1
  102. data/doc/Files/EmailLog.html +1 -1
  103. data/doc/Files/Error.html +2 -2
  104. data/doc/Files/Errors.html +1 -1
  105. data/doc/Files/EventChannel.html +1 -1
  106. data/doc/Files/EventDeliveryAttempt.html +1 -1
  107. data/doc/Files/EventRecord.html +1 -1
  108. data/doc/Files/EventSubscription.html +1 -1
  109. data/doc/Files/EventTarget.html +1 -1
  110. data/doc/Files/ExavaultApiRequestLog.html +1 -1
  111. data/doc/Files/ExceededRuntimeLimitError.html +1 -1
  112. data/doc/Files/Expectation.html +1 -1
  113. data/doc/Files/ExpectationAlreadyHasOpenWindowError.html +1 -1
  114. data/doc/Files/ExpectationEvaluation.html +1 -1
  115. data/doc/Files/ExpectationIncident.html +1 -1
  116. data/doc/Files/ExpectationNotManualTriggerError.html +1 -1
  117. data/doc/Files/ExpiredPrivateKeyError.html +1 -1
  118. data/doc/Files/ExpiredPublicKeyError.html +1 -1
  119. data/doc/Files/ExportFailureError.html +1 -1
  120. data/doc/Files/ExportNotReadyError.html +1 -1
  121. data/doc/Files/ExternalEvent.html +1 -1
  122. data/doc/Files/FailedToChangePasswordError.html +1 -1
  123. data/doc/Files/File.html +2019 -1515
  124. data/doc/Files/FileAction.html +1 -1
  125. data/doc/Files/FileActionError.html +1 -1
  126. data/doc/Files/FileComment.html +1 -1
  127. data/doc/Files/FileCommentReaction.html +1 -1
  128. data/doc/Files/FileLockedError.html +1 -1
  129. data/doc/Files/FileMigration.html +1 -1
  130. data/doc/Files/FileMigrationLog.html +1 -1
  131. data/doc/Files/FileNotFoundError.html +1 -1
  132. data/doc/Files/FileNotUploadedError.html +1 -1
  133. data/doc/Files/FilePendingProcessingError.html +1 -1
  134. data/doc/Files/FileProcessingErrorError.html +1 -1
  135. data/doc/Files/FileTooBigToDecryptError.html +1 -1
  136. data/doc/Files/FileTooBigToEncryptError.html +1 -1
  137. data/doc/Files/FileUploadNotFoundError.html +1 -1
  138. data/doc/Files/FileUploadPart.html +1 -1
  139. data/doc/Files/FileUploadedToWrongRegionError.html +1 -1
  140. data/doc/Files/FileUtils.html +1 -1
  141. data/doc/Files/FilenameTooLongError.html +1 -1
  142. data/doc/Files/FilesAgentFailedAuthorizationError.html +1 -1
  143. data/doc/Files/FilesNativeStorageOverloadedError.html +1 -1
  144. data/doc/Files/Folder.html +1 -1
  145. data/doc/Files/FolderAdminOrBillingPermissionRequiredError.html +1 -1
  146. data/doc/Files/FolderAdminPermissionRequiredError.html +1 -1
  147. data/doc/Files/FolderLockedError.html +1 -1
  148. data/doc/Files/FolderMustNotBeAFileError.html +1 -1
  149. data/doc/Files/FolderNotEmptyError.html +1 -1
  150. data/doc/Files/FoldersNotAllowedError.html +1 -1
  151. data/doc/Files/FormField.html +1 -1
  152. data/doc/Files/FormFieldSet.html +1 -1
  153. data/doc/Files/FtpActionLog.html +1 -1
  154. data/doc/Files/FullPermissionRequiredError.html +1 -1
  155. data/doc/Files/GpgKey.html +1 -1
  156. data/doc/Files/Group.html +1 -1
  157. data/doc/Files/GroupNotFoundError.html +1 -1
  158. data/doc/Files/GroupUser.html +1 -1
  159. data/doc/Files/History.html +1 -1
  160. data/doc/Files/HistoryExport.html +1 -1
  161. data/doc/Files/HistoryExportResult.html +1 -1
  162. data/doc/Files/HistoryPermissionRequiredError.html +1 -1
  163. data/doc/Files/HistoryUnavailableError.html +1 -1
  164. data/doc/Files/HolidayCalendar.html +1 -1
  165. data/doc/Files/HolidayRegion.html +1 -1
  166. data/doc/Files/Image.html +1 -1
  167. data/doc/Files/InAppAiAssistantUnavailableError.html +1 -1
  168. data/doc/Files/InboundS3Log.html +1 -1
  169. data/doc/Files/InboxNotFoundError.html +1 -1
  170. data/doc/Files/InboxRecipient.html +1 -1
  171. data/doc/Files/InboxRegistration.html +1 -1
  172. data/doc/Files/InboxRegistrationCodeFailedError.html +1 -1
  173. data/doc/Files/InboxUpload.html +1 -1
  174. data/doc/Files/InsufficientPermissionForParamsError.html +1 -1
  175. data/doc/Files/InsufficientPermissionForSiteError.html +1 -1
  176. data/doc/Files/IntegrationCentricProfile.html +1 -1
  177. data/doc/Files/InternalGeneralErrorError.html +1 -1
  178. data/doc/Files/InvalidBodyError.html +1 -1
  179. data/doc/Files/InvalidBundleCodeError.html +1 -1
  180. data/doc/Files/InvalidCredentialsError.html +1 -1
  181. data/doc/Files/InvalidCursorError.html +1 -1
  182. data/doc/Files/InvalidCursorTypeForSortError.html +1 -1
  183. data/doc/Files/InvalidEtagsError.html +1 -1
  184. data/doc/Files/InvalidFileTypeError.html +1 -1
  185. data/doc/Files/InvalidFilenameError.html +1 -1
  186. data/doc/Files/InvalidFilterAliasCombinationError.html +1 -1
  187. data/doc/Files/InvalidFilterFieldError.html +1 -1
  188. data/doc/Files/InvalidFilterParamError.html +1 -1
  189. data/doc/Files/InvalidFilterParamFormatError.html +1 -1
  190. data/doc/Files/InvalidFilterParamValueError.html +1 -1
  191. data/doc/Files/InvalidInputEncodingError.html +1 -1
  192. data/doc/Files/InvalidInterfaceError.html +1 -1
  193. data/doc/Files/InvalidOauthError.html +1 -1
  194. data/doc/Files/InvalidOauthProviderError.html +1 -1
  195. data/doc/Files/InvalidOrExpiredCodeError.html +1 -1
  196. data/doc/Files/InvalidParameterError.html +5 -1
  197. data/doc/Files/InvalidPathError.html +1 -1
  198. data/doc/Files/InvalidPriorityColorError.html +1 -1
  199. data/doc/Files/InvalidRangeError.html +1 -1
  200. data/doc/Files/InvalidReturnToUrlError.html +1 -1
  201. data/doc/Files/InvalidSearchQueryError.html +1 -1
  202. data/doc/Files/InvalidSessionError.html +1 -1
  203. data/doc/Files/InvalidSiteError.html +1 -1
  204. data/doc/Files/InvalidSortFieldError.html +1 -1
  205. data/doc/Files/InvalidSortFilterCombinationError.html +1 -1
  206. data/doc/Files/InvalidUploadOffsetError.html +1 -1
  207. data/doc/Files/InvalidUploadPartGapError.html +1 -1
  208. data/doc/Files/InvalidUploadPartSizeError.html +1 -1
  209. data/doc/Files/InvalidUsernameOrPasswordError.html +1 -1
  210. data/doc/Files/InvalidWorkspaceIdHeaderError.html +1 -1
  211. data/doc/Files/InvalidZipFileError.html +1 -1
  212. data/doc/Files/Invoice.html +1 -1
  213. data/doc/Files/InvoiceLineItem.html +1 -1
  214. data/doc/Files/IpAddress.html +1 -1
  215. data/doc/Files/KeyLifecycleRule.html +1 -1
  216. data/doc/Files/List.html +1 -1
  217. data/doc/Files/Lock.html +1 -1
  218. data/doc/Files/LockOperationBusyError.html +1 -1
  219. data/doc/Files/LockedOutError.html +1 -1
  220. data/doc/Files/LockoutRegionMismatchError.html +1 -1
  221. data/doc/Files/MetadataCategory.html +1 -1
  222. data/doc/Files/MetadataNotSupportedOnRemotesError.html +1 -1
  223. data/doc/Files/MethodNotAllowedError.html +1 -1
  224. data/doc/Files/MigrationInProgressError.html +1 -1
  225. data/doc/Files/MissingParameterError.html +1 -1
  226. data/doc/Files/ModelSaveErrorError.html +1 -1
  227. data/doc/Files/MoverAccessDeniedError.html +1 -1
  228. data/doc/Files/MoverPackageRequiredError.html +1 -1
  229. data/doc/Files/MultipleProcessingErrorsError.html +1 -1
  230. data/doc/Files/MultipleSortParamsNotAllowedError.html +1 -1
  231. data/doc/Files/MustAuthenticateWithApiKeyError.html +1 -1
  232. data/doc/Files/NeedAdminPermissionForInboxError.html +1 -1
  233. data/doc/Files/NestedNotFoundError.html +1 -1
  234. data/doc/Files/NoAccountForSiteError.html +1 -1
  235. data/doc/Files/NoValidInputParamsError.html +1 -1
  236. data/doc/Files/NonAdminsMustQueryByFolderOrPathError.html +1 -1
  237. data/doc/Files/NotAllowedToCreateBundleError.html +1 -1
  238. data/doc/Files/NotAuthenticatedError.html +1 -1
  239. data/doc/Files/NotAuthorizedError.html +1 -1
  240. data/doc/Files/NotEnqueuableSyncError.html +1 -1
  241. data/doc/Files/NotFoundError.html +1 -1
  242. data/doc/Files/NotImplementedError.html +1 -1
  243. data/doc/Files/Notification.html +1 -1
  244. data/doc/Files/OffsetUploadNotAllowedWithMalwareScanningError.html +1 -1
  245. data/doc/Files/OneTimePasswordIncorrectError.html +1 -1
  246. data/doc/Files/OutboundConnectionLog.html +1 -1
  247. data/doc/Files/PartNumberTooLargeError.html +1 -1
  248. data/doc/Files/Partner.html +1 -1
  249. data/doc/Files/PartnerChannel.html +1 -1
  250. data/doc/Files/PartnerChannelTemplate.html +1 -1
  251. data/doc/Files/PartnerConnection.html +1 -1
  252. data/doc/Files/PartnerSite.html +1 -1
  253. data/doc/Files/PartnerSiteRequest.html +1 -1
  254. data/doc/Files/PasswordChangeNotRequiredError.html +1 -1
  255. data/doc/Files/PasswordChangeRequiredError.html +1 -1
  256. data/doc/Files/PathCannotHaveTrailingWhitespaceError.html +1 -1
  257. data/doc/Files/PathTooLongError.html +1 -1
  258. data/doc/Files/PathUtil.html +1 -1
  259. data/doc/Files/Payment.html +1 -1
  260. data/doc/Files/PaymentLineItem.html +1 -1
  261. data/doc/Files/PaymentMethodErrorError.html +1 -1
  262. data/doc/Files/PendingWorkEvent.html +1 -1
  263. data/doc/Files/Permission.html +1 -1
  264. data/doc/Files/PlanNotFoundError.html +1 -1
  265. data/doc/Files/Preview.html +1 -1
  266. data/doc/Files/PreviewOnlyPermissionCannotDownloadError.html +1 -1
  267. data/doc/Files/ProcessingFailureError.html +1 -1
  268. data/doc/Files/PublicHostingRequestLog.html +1 -1
  269. data/doc/Files/PublicIpAddress.html +1 -1
  270. data/doc/Files/PublicKey.html +1 -1
  271. data/doc/Files/RateLimitedError.html +1 -1
  272. data/doc/Files/ReadOnlySessionError.html +1 -1
  273. data/doc/Files/ReadPermissionRequiredError.html +1 -1
  274. data/doc/Files/ReauthenticationFailedError.html +1 -1
  275. data/doc/Files/ReauthenticationFailedFinalError.html +1 -1
  276. data/doc/Files/ReauthenticationNeededActionError.html +1 -1
  277. data/doc/Files/ReauthenticationNeededFieldsError.html +1 -1
  278. data/doc/Files/ReauthenticationRateLimitedError.html +1 -1
  279. data/doc/Files/RecaptchaFailedError.html +1 -1
  280. data/doc/Files/RecipientAlreadySharedError.html +1 -1
  281. data/doc/Files/RemoteBandwidthSnapshot.html +1 -1
  282. data/doc/Files/RemoteDesktopDebugLoggingDisabledError.html +1 -1
  283. data/doc/Files/RemoteEntryReadOnlyError.html +1 -1
  284. data/doc/Files/RemoteMountBackend.html +1 -1
  285. data/doc/Files/RemoteServer.html +1 -1
  286. data/doc/Files/RemoteServerConfigurationFile.html +1 -1
  287. data/doc/Files/RemoteServerCredential.html +1 -1
  288. data/doc/Files/RemoteServerErrorError.html +1 -1
  289. data/doc/Files/Request.html +1 -1
  290. data/doc/Files/RequestBodyTooLargeError.html +1 -1
  291. data/doc/Files/RequestParamsContainInvalidCharacterError.html +1 -1
  292. data/doc/Files/RequestParamsInvalidError.html +1 -1
  293. data/doc/Files/RequestParamsRequiredError.html +1 -1
  294. data/doc/Files/ResourceBelongsToParentSiteError.html +1 -1
  295. data/doc/Files/ResourceLockedError.html +1 -1
  296. data/doc/Files/Response.html +1 -1
  297. data/doc/Files/Restore.html +1 -1
  298. data/doc/Files/RootFolderBehaviorSiteAdminRequiredError.html +1 -1
  299. data/doc/Files/RootFolderBehaviorSkipSiteAdminRequiredError.html +1 -1
  300. data/doc/Files/Schedule.html +1 -1
  301. data/doc/Files/ScheduledExport.html +1 -1
  302. data/doc/Files/ScimLog.html +1 -1
  303. data/doc/Files/SearchAllOnChildPathError.html +1 -1
  304. data/doc/Files/SearchUnavailableError.html +1 -1
  305. data/doc/Files/Secret.html +1 -1
  306. data/doc/Files/SelfManagedRequiredError.html +1 -1
  307. data/doc/Files/ServiceUnavailableError.html +1 -1
  308. data/doc/Files/Session.html +1 -1
  309. data/doc/Files/SettingsChange.html +1 -1
  310. data/doc/Files/SftpActionLog.html +1 -1
  311. data/doc/Files/SftpHostKey.html +1 -1
  312. data/doc/Files/ShareGroup.html +1 -1
  313. data/doc/Files/ShareGroupMember.html +1 -1
  314. data/doc/Files/SiemHttpDestination.html +1 -1
  315. data/doc/Files/SiemHttpDestinationEvent.html +1 -1
  316. data/doc/Files/Site.html +911 -731
  317. data/doc/Files/SiteAdminOrPartnerAdminPermissionRequiredError.html +1 -1
  318. data/doc/Files/SiteAdminOrWorkspaceAdminOrFolderAdminPermissionRequiredError.html +1 -1
  319. data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminOrFolderAdminPermissionRequiredError.html +1 -1
  320. data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminPermissionRequiredError.html +1 -1
  321. data/doc/Files/SiteAdminOrWorkspaceAdminPermissionRequiredError.html +1 -1
  322. data/doc/Files/SiteAdminRequiredError.html +1 -1
  323. data/doc/Files/SiteConfigurationError.html +1 -1
  324. data/doc/Files/SiteDisabledError.html +1 -1
  325. data/doc/Files/SiteFilesAreImmutableError.html +1 -1
  326. data/doc/Files/SiteNotFoundError.html +1 -1
  327. data/doc/Files/SiteSubdomainRedirect.html +1 -1
  328. data/doc/Files/SiteWasRemovedError.html +1 -1
  329. data/doc/Files/SizableIO.html +1 -1
  330. data/doc/Files/Snapshot.html +1 -1
  331. data/doc/Files/SsoEvent.html +1 -1
  332. data/doc/Files/SsoStrategy.html +1 -1
  333. data/doc/Files/Status.html +1 -1
  334. data/doc/Files/Style.html +1 -1
  335. data/doc/Files/SubfolderLockedError.html +1 -1
  336. data/doc/Files/Sync.html +1 -1
  337. data/doc/Files/SyncInProgressError.html +1 -1
  338. data/doc/Files/SyncLog.html +1 -1
  339. data/doc/Files/SyncRun.html +1 -1
  340. data/doc/Files/SyncRunLiveTransfer.html +1 -1
  341. data/doc/Files/SystemProfiler.html +1 -1
  342. data/doc/Files/TooManyConcurrentLoginsError.html +1 -1
  343. data/doc/Files/TooManyConcurrentRequestsError.html +1 -1
  344. data/doc/Files/TooManyLoginAttemptsError.html +1 -1
  345. data/doc/Files/TooManyRequestsError.html +1 -1
  346. data/doc/Files/TooManySharesError.html +1 -1
  347. data/doc/Files/Transfer/BufferLimitError.html +175 -0
  348. data/doc/Files/Transfer/ByteBudget/Reservation.html +301 -0
  349. data/doc/Files/Transfer/ByteBudget.html +748 -0
  350. data/doc/Files/Transfer/CancelledError.html +235 -0
  351. data/doc/Files/Transfer/Checkpoint.html +1371 -0
  352. data/doc/Files/Transfer/CheckpointError.html +173 -0
  353. data/doc/Files/Transfer/ClientTransport/ClientResponse.html +661 -0
  354. data/doc/Files/Transfer/ClientTransport/Reader.html +530 -0
  355. data/doc/Files/Transfer/ClientTransport.html +675 -0
  356. data/doc/Files/Transfer/Clock.html +189 -0
  357. data/doc/Files/Transfer/Control.html +667 -0
  358. data/doc/Files/Transfer/Controller/Attempt.html +465 -0
  359. data/doc/Files/Transfer/Controller.html +1166 -0
  360. data/doc/Files/Transfer/Coordinator/Timing.html +568 -0
  361. data/doc/Files/Transfer/Coordinator.html +534 -0
  362. data/doc/Files/Transfer/DownloadCoordinator/FileSink.html +976 -0
  363. data/doc/Files/Transfer/DownloadCoordinator/IoSink.html +1168 -0
  364. data/doc/Files/Transfer/DownloadCoordinator/Piece.html +875 -0
  365. data/doc/Files/Transfer/DownloadCoordinator.html +728 -0
  366. data/doc/Files/Transfer/FileSlots.html +480 -0
  367. data/doc/Files/Transfer/FrontendResponseError.html +235 -0
  368. data/doc/Files/Transfer/Holds.html +505 -0
  369. data/doc/Files/Transfer/HttpTransport.html +579 -0
  370. data/doc/Files/Transfer/Job.html +2338 -0
  371. data/doc/Files/Transfer/Options.html +924 -0
  372. data/doc/Files/Transfer/PausedError.html +319 -0
  373. data/doc/Files/Transfer/Policy.html +1642 -0
  374. data/doc/Files/Transfer/RequestPermits.html +160 -0
  375. data/doc/Files/Transfer/SourceChangedError.html +235 -0
  376. data/doc/Files/Transfer/StorageResponse.html +546 -0
  377. data/doc/Files/Transfer/StorageRetry.html +1098 -0
  378. data/doc/Files/Transfer/UploadCoordinator/Grant.html +1048 -0
  379. data/doc/Files/Transfer/UploadCoordinator/Part.html +1048 -0
  380. data/doc/Files/Transfer/UploadCoordinator/Region.html +295 -0
  381. data/doc/Files/Transfer/UploadCoordinator/Segments.html +299 -0
  382. data/doc/Files/Transfer/UploadCoordinator/Source.html +725 -0
  383. data/doc/Files/Transfer/UploadCoordinator/StreamSource.html +664 -0
  384. data/doc/Files/Transfer/UploadCoordinator.html +546 -0
  385. data/doc/Files/Transfer/UploadPlan.html +522 -0
  386. data/doc/Files/Transfer/VersionChangedError.html +235 -0
  387. data/doc/Files/Transfer.html +134 -0
  388. data/doc/Files/TrialExpiredError.html +1 -1
  389. data/doc/Files/TrialLockedError.html +1 -1
  390. data/doc/Files/TwoFactorAuthenticationCodeAlreadySentError.html +1 -1
  391. data/doc/Files/TwoFactorAuthenticationCountryBlacklistedError.html +1 -1
  392. data/doc/Files/TwoFactorAuthenticationErrorError.html +1 -1
  393. data/doc/Files/TwoFactorAuthenticationGeneralErrorError.html +1 -1
  394. data/doc/Files/TwoFactorAuthenticationMethodUnsupportedErrorError.html +1 -1
  395. data/doc/Files/TwoFactorAuthenticationRequiredError.html +1 -1
  396. data/doc/Files/TwoFactorAuthenticationSetupExpiredError.html +1 -1
  397. data/doc/Files/TwoFactorAuthenticationUnsubscribedRecipientError.html +1 -1
  398. data/doc/Files/URI.html +1 -1
  399. data/doc/Files/UnrecognizedSortIndexError.html +1 -1
  400. data/doc/Files/UnsupportedCurrencyError.html +1 -1
  401. data/doc/Files/UnsupportedHttpResponseFormatError.html +1 -1
  402. data/doc/Files/UnsupportedMediaTypeError.html +1 -1
  403. data/doc/Files/UpdatesNotAllowedForRemotesError.html +1 -1
  404. data/doc/Files/UploadsUnavailableError.html +1 -1
  405. data/doc/Files/UsageByTopLevelDir.html +1 -1
  406. data/doc/Files/UsageDailySnapshot.html +1 -1
  407. data/doc/Files/UsageSnapshot.html +1 -1
  408. data/doc/Files/User.html +597 -386
  409. data/doc/Files/UserAdditionalEmailRecipient.html +1 -1
  410. data/doc/Files/UserCipherUse.html +1 -1
  411. data/doc/Files/UserIdInvalidError.html +1 -1
  412. data/doc/Files/UserIdOnUserEndpointError.html +1 -1
  413. data/doc/Files/UserIdWithoutSiteAdminError.html +1 -1
  414. data/doc/Files/UserLifecycleRule.html +1 -1
  415. data/doc/Files/UserNotFoundError.html +1 -1
  416. data/doc/Files/UserRequest.html +1 -1
  417. data/doc/Files/UserRequestsEnabledRequiredError.html +1 -1
  418. data/doc/Files/UserRequiredError.html +1 -1
  419. data/doc/Files/UserSecurityEvent.html +1 -1
  420. data/doc/Files/UserSftpClientUse.html +1 -1
  421. data/doc/Files/Util/LogSettings.html +1 -1
  422. data/doc/Files/Util.html +1 -1
  423. data/doc/Files/WebDavActionLog.html +1 -1
  424. data/doc/Files/WebhookTest.html +1 -1
  425. data/doc/Files/Workspace.html +1 -1
  426. data/doc/Files/WriteAndBundlePermissionRequiredError.html +1 -1
  427. data/doc/Files/WritePermissionRequiredError.html +1 -1
  428. data/doc/Files/ZipListEntry.html +1 -1
  429. data/doc/Files.html +116 -116
  430. data/doc/_index.html +314 -4
  431. data/doc/class_list.html +1 -1
  432. data/doc/file.README.html +1 -1
  433. data/doc/index.html +1 -1
  434. data/doc/method_list.html +5368 -3048
  435. data/doc/top-level-namespace.html +1 -1
  436. data/docs/file.md +346 -0
  437. data/docs/site.md +10 -0
  438. data/docs/user.md +8 -0
  439. data/lib/files.com/api.rb +6 -1
  440. data/lib/files.com/api_client.rb +220 -32
  441. data/lib/files.com/models/file.rb +124 -17
  442. data/lib/files.com/models/site.rb +16 -0
  443. data/lib/files.com/models/user.rb +19 -0
  444. data/lib/files.com/transfer/budgets.rb +123 -0
  445. data/lib/files.com/transfer/checkpoint.rb +113 -0
  446. data/lib/files.com/transfer/clock.rb +14 -0
  447. data/lib/files.com/transfer/controller.rb +549 -0
  448. data/lib/files.com/transfer/download_coordinator.rb +906 -0
  449. data/lib/files.com/transfer/errors.rb +100 -0
  450. data/lib/files.com/transfer/http_transport.rb +337 -0
  451. data/lib/files.com/transfer/job.rb +778 -0
  452. data/lib/files.com/transfer/options.rb +126 -0
  453. data/lib/files.com/transfer/policy.rb +91 -0
  454. data/lib/files.com/transfer/storage_retry.rb +169 -0
  455. data/lib/files.com/transfer/upload_coordinator.rb +657 -0
  456. data/lib/files.com/transfer/upload_plan.rb +157 -0
  457. data/lib/files.com.rb +13 -0
  458. data/spec/lib/api_client_spec.rb +125 -3
  459. data/spec/models/file_transfer_spec.rb +53 -4
  460. data/spec/support/transfer_server.rb +113 -14
  461. data/spec/transfer/adaptive_download_spec.rb +1102 -0
  462. data/spec/transfer/adaptive_upload_spec.rb +1602 -0
  463. data/spec/transfer/concurrency_controller_spec.rb +382 -0
  464. data/spec/workspace_id_spec.rb +19 -14
  465. metadata +59 -1
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ # Adaptive transfers: uploads and downloads that send their parts concurrently and tune how many are in flight to
5
+ # what the link sustains, within the limits the caller sets. They are opt-in, through the transfer: option of
6
+ # Files::File.upload_file, Files::File.upload_io (with a known size), #upload_file, #download_file and
7
+ # #download_content (see docs/file.md); without it every transfer works as it always has.
8
+ module Transfer
9
+ # Raised by a transfer whose Control was cancelled, once the requests it had in flight have settled. Nothing is
10
+ # finalized after it.
11
+ class CancelledError < Error
12
+ def initialize(message = "The transfer was cancelled")
13
+ super
14
+ end
15
+ end
16
+
17
+ # Raised by a transfer whose Control was paused, once the requests it had in flight have settled. checkpoint
18
+ # resumes it in this process with Files::File.resume_upload or Files::File.resume_download; it is nil when what was
19
+ # transferred cannot be continued: a transfer paused before it started, an upload from a caller's stream, which
20
+ # cannot be read again, or a download into a caller's IO that can neither start over nor report where its bytes
21
+ # began. A resume paused before its turn, or before it finished checking the local file or destination, gives back
22
+ # the checkpoint it was given, still usable.
23
+ class PausedError < Error
24
+ attr_reader :checkpoint
25
+
26
+ def initialize(checkpoint = nil, message = "The transfer was paused")
27
+ super(message)
28
+ @checkpoint = checkpoint
29
+ end
30
+ end
31
+
32
+ # A part needs more memory than the transfer's buffer_bytes allows. It is raised before anything is read for that
33
+ # part, so raise buffer_bytes or transfer without transfer:. An adaptive download through a caller's client raises
34
+ # it, before it sends a content request or writes anything, when the client's adapter is not one it relies on to
35
+ # stream a response
36
+ # through Faraday's on_data (Faraday's net_http or net_http_persistent), and refuses with it a 2xx response such an
37
+ # adapter still read whole.
38
+ class BufferLimitError < InvalidParameterError; end
39
+
40
+ # The remote file changed while it was downloading: storage refused a range for the version the download began
41
+ # with, or answered with another version.
42
+ class VersionChangedError < Error
43
+ def initialize(message = "The remote file changed during the download")
44
+ super
45
+ end
46
+ end
47
+
48
+ # A response that came from the Files.com web app rather than file storage, such as a sign-in page. Nothing from
49
+ # it is written.
50
+ class FrontendResponseError < Error
51
+ def initialize(message = "The transfer was answered by the Files.com web app instead of file storage")
52
+ super
53
+ end
54
+ end
55
+
56
+ # The local file being uploaded changed or ended early while its parts were being sent, or a caller's stream ended
57
+ # before the size it was given. The upload is not finalized.
58
+ class SourceChangedError < Error
59
+ def initialize(message = "The local file changed during the upload")
60
+ super
61
+ end
62
+ end
63
+
64
+ # A checkpoint that cannot resume: it came from another process, another resume is using it, a resume already
65
+ # started from it, or the local file, the destination (including the bytes already written to it, which must be
66
+ # read back to be checked) or the remote file is no longer the one it was taken from. Nothing is sent, written or
67
+ # truncated before it is raised.
68
+ class CheckpointError < InvalidParameterError; end
69
+
70
+ # A request that failed before a whole response arrived. retryable? is false for a TLS failure, which repeating
71
+ # cannot fix. Coordinators raise original (downloads) or an APIConnectionError (uploads) in its place, as the
72
+ # transfers without transfer: do.
73
+ class NetworkFailure < StandardError
74
+ attr_reader :original
75
+
76
+ def initialize(original, retryable: true)
77
+ super("Transfer request failed (#{original.class})")
78
+ @original = original
79
+ @retryable = retryable
80
+ end
81
+
82
+ def retryable?
83
+ @retryable
84
+ end
85
+ end
86
+
87
+ # Carries an error from the caller's source or destination through the transport unchanged, so it is never taken
88
+ # for a network failure and retried.
89
+ class Passthrough < StandardError
90
+ attr_reader :error
91
+
92
+ def initialize(error)
93
+ super("Transfer source or destination failed (#{error.class})")
94
+ @error = error
95
+ end
96
+ end
97
+
98
+ private_constant :NetworkFailure, :Passthrough
99
+ end
100
+ end
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ module Transfer
5
+ # A storage response: its status, its headers as lowercase names each with its values, and its body: what the
6
+ # success handler returned, or at most the first 64 KiB of any other response, with truncated true when that
7
+ # response had more.
8
+ StorageResponse = Struct.new(:status, :headers, :body, :truncated, keyword_init: true) do
9
+ def header(name)
10
+ headers.fetch(name, []).first
11
+ end
12
+ end
13
+
14
+ # Sends a job's content requests with Net::HTTP over connections each worker thread owns, reused for its next
15
+ # request to the same origin. It never follows a redirect or retries by itself, verifies TLS certificates and host
16
+ # names, and uses Files.proxy, or the proxy environment variables without it, with Files.open_timeout and
17
+ # Files.read_timeout (for each read and each write) as they were when the job began. It carries no Files.com
18
+ # credentials: a signed URL is its own authority.
19
+ class HttpTransport
20
+ ERROR_BODY_BYTES = 64 * 1024
21
+ KEEP_ALIVE_SECONDS = 30
22
+ RETRYABLE_ERRORS = [ IOError, SystemCallError, SocketError, Timeout::Error, Net::ProtocolError, Net::HTTPBadResponse ].freeze
23
+
24
+ # Whether client sends requests just as this transport does: the SDK's own ApiClient with no request handling or
25
+ # logging of its own (ApiClient#default_transfer_behavior?), over a connection ApiClient.build_default_conn made
26
+ # with this transport's own proxy, its user and password included, or, as this transport, with none, and with
27
+ # nothing about it changed since (ApiClient.unchanged_default_conn?). Any other client, such as one made after
28
+ # Files.proxy changed, keeps its connection and its settings, such as a minimum TLS version, an adapter
29
+ # configuration block or its proxy, its remote_request and its logging for the transfer, one request at a time,
30
+ # through ClientTransport.
31
+ def compatible?(client)
32
+ return false unless client.respond_to?(:default_transfer_behavior?) && client.default_transfer_behavior?
33
+
34
+ ApiClient.unchanged_default_conn?(client.conn, @proxy_identity)
35
+ end
36
+
37
+ def initialize
38
+ proxy = Files.proxy
39
+ @proxy_identity = ApiClient.proxy_identity(proxy)
40
+ @proxy = @proxy_identity && Faraday::ProxyOptions.from(proxy)
41
+ @open_timeout = Files.open_timeout
42
+ @read_timeout = Files.read_timeout
43
+ end
44
+
45
+ def serialized?
46
+ false
47
+ end
48
+
49
+ # Sends one request on the calling thread over its connections, a Hash that thread owns, and returns its
50
+ # StorageResponse. body is a String, or an object whose read(length, buffer) gives length bytes in all, streamed
51
+ # without holding them. With a block, a 2xx response is passed to it with its body unread, and what it returns is
52
+ # the response's body; the block reads it as it arrives. An error from the block is raised as it is, unless it is a
53
+ # network error, which is raised, as one before the response, as a NetworkFailure. timing, when given, is told as
54
+ # the send starts (connection setup included), as the response headers arrive, and once the block, or the read of
55
+ # any other response's body, has finished.
56
+ def perform(method, url, headers, connections, body: nil, length: nil, timing: nil, &on_success)
57
+ uri = ::URI.parse(url)
58
+ request = Net::HTTPGenericRequest.new(method.to_s.upcase, !body.nil?, true, uri.request_uri, headers)
59
+ if body.is_a?(String)
60
+ request.body = body
61
+ elsif body
62
+ request.body_stream = body
63
+ request.content_length = length
64
+ end
65
+ result = nil
66
+ timing&.sending
67
+ connection(uri, connections).request(request) do |response|
68
+ timing&.headers
69
+ kept, truncated = on_success && response.is_a?(Net::HTTPSuccess) ? [ on_success.call(response), false ] : limited_body(response)
70
+ timing&.body
71
+ result = StorageResponse.new(status: response.code.to_i, headers: response.to_hash, body: kept, truncated: truncated)
72
+ end
73
+ result
74
+ rescue OpenSSL::SSL::SSLError => e
75
+ drop(connections, uri)
76
+ raise NetworkFailure.new(e, retryable: false), cause: nil
77
+ rescue *RETRYABLE_ERRORS => e
78
+ drop(connections, uri)
79
+ raise NetworkFailure.new(e), cause: nil
80
+ end
81
+
82
+ def close_all(connections)
83
+ connections.each_value { |http| finish(http) }
84
+ connections.clear
85
+ end
86
+
87
+ private def connection(uri, connections)
88
+ key = [ uri.scheme, uri.hostname, uri.port ]
89
+ http = connections[key]
90
+ return http if http&.started?
91
+
92
+ http = build_http(uri)
93
+ http.start
94
+ connections[key] = http
95
+ end
96
+
97
+ private def build_http(uri)
98
+ http = if @proxy
99
+ Net::HTTP.new(uri.hostname, uri.port, @proxy.uri.hostname, @proxy.uri.port, @proxy.user, @proxy.password)
100
+ else
101
+ Net::HTTP.new(uri.hostname, uri.port)
102
+ end
103
+ http.use_ssl = uri.scheme == "https"
104
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER if http.use_ssl?
105
+ http.open_timeout = @open_timeout
106
+ http.read_timeout = @read_timeout
107
+ http.write_timeout = @read_timeout
108
+ http.max_retries = 0
109
+ http.keep_alive_timeout = KEEP_ALIVE_SECONDS
110
+ http
111
+ end
112
+
113
+ # The first ERROR_BODY_BYTES of a response's body, which is read to its end, and whether it had more.
114
+ private def limited_body(response)
115
+ kept = String.new(encoding: Encoding::BINARY)
116
+ truncated = false
117
+ response.read_body do |chunk|
118
+ room = ERROR_BODY_BYTES - kept.bytesize
119
+ truncated ||= chunk.bytesize > room
120
+ kept << chunk.byteslice(0, room) if room.positive?
121
+ end
122
+ [ kept, truncated ]
123
+ end
124
+
125
+ private def drop(connections, uri)
126
+ finish(connections.delete([ uri.scheme, uri.hostname, uri.port ])) if uri
127
+ end
128
+
129
+ private def finish(http)
130
+ http.finish if http&.started?
131
+ rescue IOError, SystemCallError
132
+ nil
133
+ end
134
+ end
135
+
136
+ # Sends a transfer's content requests through the caller's own client, which HttpTransport cannot stand in for:
137
+ # one with its own adapter, middleware, request handling (an overridden remote_request), logger, or connection
138
+ # settings, such as a minimum TLS version or an adapter configuration block. Each request goes through the client's
139
+ # remote_request exactly once (ApiClient.single_attempt), so the client's hooks, logging, settings and errors still
140
+ # apply while every retry stays the transfer's own, counted and admitted like any other. It sends one request at a
141
+ # time, since such a client may not be safe to share between threads, and whole-String bodies, since its adapter
142
+ # may not stream them.
143
+ #
144
+ # A response a success handler reads is streamed to it as it arrives, through Faraday's on_data, so nothing of it is
145
+ # held here beyond what the handler keeps; any other response keeps its first 64 KiB, and says whether it had more.
146
+ # The handler runs in a Fiber of its own, with the client ApiClient#request made active for the thread that sent the
147
+ # request, so what it calls, such as a caller's progress callback, makes its SDK calls with it. A download relies
148
+ # on that streaming, so
149
+ # it goes through a client only when the client's adapter is one that streams (streams?), and refuses any other
150
+ # before it requests or writes anything; an upload's responses are small, and any adapter carries them. A 2xx
151
+ # response such an adapter still read whole is refused, never handed on. A body shorter than its headers said is a
152
+ # network failure, as through HttpTransport. The job's diagnostics say when a transfer uses it.
153
+ class ClientTransport
154
+ # The adapters a download relies on to stream: as their pinned versions, faraday-net_http 3.0 and
155
+ # faraday-net_http_persistent 2.1, do, each saves a response's status and headers in env, then hands on each chunk
156
+ # of its body to on_data as Net::HTTP reads it, holding none of it, with any options or configuration block given.
157
+ STREAMING_ADAPTERS = %w[Faraday::Adapter::NetHttp Faraday::Adapter::NetHttpPersistent].freeze
158
+ NOT_STREAMING = "The download client's adapter cannot stream a response through Faraday's on_data, so an adaptive download " \
159
+ "cannot keep it within buffer_bytes; give the client Faraday's net_http or net_http_persistent adapter, or " \
160
+ "download without transfer:"
161
+ ADAPTER_BUFFERED = "The download client's adapter did not stream the response through Faraday's on_data, so the transfer cannot " \
162
+ "keep it within buffer_bytes; give the client an adapter that streams, or download without transfer:"
163
+
164
+ # Whether client's adapter is exactly one of STREAMING_ADAPTERS, so a download can go through it.
165
+ def self.streams?(client)
166
+ conn = client.respond_to?(:conn) ? client.conn : nil
167
+ conn.is_a?(Faraday::Connection) && STREAMING_ADAPTERS.include?(conn.builder.adapter&.name)
168
+ end
169
+
170
+ # A streamed 2xx response the client hands over, given to a success handler as HttpTransport gives it a
171
+ # Net::HTTPResponse; its body arrives through a Reader's Fiber.
172
+ class ClientResponse
173
+ attr_reader :code
174
+
175
+ def initialize(status, headers)
176
+ @code = status.to_s
177
+ @headers = headers
178
+ end
179
+
180
+ def [](name)
181
+ @headers.fetch(name.to_s.downcase, []).first
182
+ end
183
+
184
+ def key?(name)
185
+ @headers.key?(name.to_s.downcase)
186
+ end
187
+
188
+ def to_hash
189
+ @headers
190
+ end
191
+
192
+ def content_length
193
+ value = self["content-length"]
194
+ value&.match?(/\A\d+\z/) ? value.to_i : nil
195
+ end
196
+
197
+ def chunked?
198
+ self["transfer-encoding"].to_s.downcase.include?("chunked")
199
+ end
200
+
201
+ def read_body
202
+ while (chunk = Fiber.yield)
203
+ yield chunk
204
+ end
205
+ end
206
+ end
207
+
208
+ # Faraday's on_data for one request. It runs a success handler in a Fiber that waits for each chunk as it arrives,
209
+ # and keeps the first 64 KiB of any other response.
210
+ class Reader
211
+ def initialize(on_success, timing)
212
+ @on_success = on_success
213
+ @timing = timing
214
+ @fiber = nil
215
+ @result = nil
216
+ @kept = String.new(encoding: Encoding::BINARY)
217
+ @truncated = false
218
+ @streamed = false
219
+ end
220
+
221
+ def streamed?
222
+ @streamed
223
+ end
224
+
225
+ # Whether a response other than a success had more than the bytes kept.
226
+ def truncated?
227
+ @truncated
228
+ end
229
+
230
+ # A chunk, the bytes so far and, since Faraday 2.5, the request's env, which holds the response's status and
231
+ # headers before its first chunk.
232
+ def call(chunk, _received, env = nil)
233
+ unless @streamed
234
+ @streamed = true
235
+ @timing&.headers
236
+ raise BufferLimitError, ADAPTER_BUFFERED if env.nil? || env.status.nil?
237
+
238
+ start(env.status.to_i, env.response_headers)
239
+ end
240
+ if @fiber
241
+ @fiber.resume(chunk.b) if @fiber.alive? && !chunk.empty?
242
+ else
243
+ room = HttpTransport::ERROR_BODY_BYTES - @kept.bytesize
244
+ @truncated ||= chunk.bytesize > room
245
+ @kept << chunk.b.byteslice(0, room) if room.positive?
246
+ end
247
+ end
248
+
249
+ # After the response: what the success handler returned once it read the end of the body, or the bytes kept.
250
+ def result
251
+ @fiber.resume(nil) while @fiber&.alive?
252
+ @fiber ? @result : @kept
253
+ end
254
+
255
+ # The handler's Fiber would not see the client ApiClient#request made active on this thread, since Thread#[] is
256
+ # per Fiber, so that client is made active in it too.
257
+ private def start(status, headers)
258
+ return unless status.between?(200, 299)
259
+
260
+ response = ClientResponse.new(status, ClientTransport.names(headers))
261
+ client = Thread.current[:files_api_client]
262
+ @fiber = Fiber.new do
263
+ Thread.current[:files_api_client] = client
264
+ @result = @on_success.call(response)
265
+ end
266
+ @fiber.resume
267
+ end
268
+ end
269
+
270
+ # Lowercase header names, each with its value; Faraday joins a repeated header's values with ", ".
271
+ def self.names(headers)
272
+ (headers || {}).each_with_object({}) { |(name, value), all| all[name.to_s.downcase] = [ value.to_s ] }
273
+ end
274
+
275
+ def initialize(client)
276
+ @client = client
277
+ @lock = Mutex.new
278
+ @open_timeout = Files.open_timeout
279
+ @read_timeout = Files.read_timeout
280
+ end
281
+
282
+ def serialized?
283
+ true
284
+ end
285
+
286
+ # As HttpTransport#perform, through the client's remote_request.
287
+ def perform(method, url, headers, _connections, body: nil, length: nil, timing: nil, &on_success)
288
+ raise ArgumentError, "a client transfer sends a String body of #{length} bytes" unless body.nil? || body.is_a?(String)
289
+
290
+ @lock.synchronize do
291
+ reader = on_success && Reader.new(on_success, timing)
292
+ timing&.sending
293
+ begin
294
+ response = ApiClient.single_attempt do
295
+ @client.remote_request(method.to_s.downcase.to_sym, url, headers, body) do |request|
296
+ request.options.open_timeout = @open_timeout
297
+ request.options.timeout = @read_timeout
298
+ request.options.on_data = reader.method(:call).to_proc if reader
299
+ end
300
+ end
301
+ timing&.headers
302
+ respond(reader, response.status, response.headers, response.body).tap { timing&.body }
303
+ rescue Faraday::SSLError => e
304
+ raise NetworkFailure.new(e, retryable: false), cause: nil
305
+ rescue Faraday::Error => e
306
+ raise NetworkFailure.new(e), cause: nil unless e.response
307
+
308
+ timing&.headers
309
+ respond(reader, e.response[:status], e.response[:headers], e.response[:body]).tap { timing&.body }
310
+ end
311
+ end
312
+ rescue IOError => e
313
+ raise NetworkFailure.new(e), cause: nil
314
+ end
315
+
316
+ def close_all(_connections); end
317
+
318
+ # A success handler gets only a streamed body: a 2xx response the adapter read whole has already been held, so it
319
+ # is refused rather than handed on. Any other response keeps its first 64 KiB, and says whether it had more.
320
+ private def respond(reader, status, headers, body)
321
+ names = ClientTransport.names(headers)
322
+ status = status.to_i
323
+ if reader&.streamed?
324
+ kept = reader.result
325
+ truncated = reader.truncated?
326
+ elsif reader && status.between?(200, 299)
327
+ raise BufferLimitError, ADAPTER_BUFFERED
328
+ else
329
+ body = body.to_s
330
+ kept = body.byteslice(0, HttpTransport::ERROR_BODY_BYTES).b
331
+ truncated = body.bytesize > HttpTransport::ERROR_BODY_BYTES
332
+ end
333
+ StorageResponse.new(status: status, headers: names, body: kept, truncated: truncated)
334
+ end
335
+ end
336
+ end
337
+ end