Workhorse handlers

Long HTTP requests are hard to handle efficiently in Rails. The requests are either memory-inefficient (file uploads) or impossible at all due to shorter timeouts (for example, Puma server has 60-second timeout). Workhorse can efficiently handle a large number of long HTTP requests. Workhorse acts as a proxy that intercepts all HTTP requests and either propagates them without changing or handles them itself by performing additional logic.

Injectors

RailsWorkhorseClientRailsWorkhorseClientRequestPropagate the request as-isRespond with a special header that contains instructions for proceeding with the requestResponse

Example: Send a Git blob

GitalyRailsWorkhorseClientGitalyRailsWorkhorseClientHTTP Request for a blobPropagate the request as-isRespond with a git-blob:{encoded_data} headerBlobService.GetBlob gRPC requestBlobService.GetBlob gRPC requestStream the data

How GitLab Rails processes the request

How Workhorse processes the header

Example: Send a file

Object StorageRailsWorkhorseClientObject StorageRailsWorkhorseClientHTTP Request for a filePropagate the request as-isRespond with a send-url:{encoded_data} headerRequest for a fileStream the dataStream the data

Pre-authorized requests

Object StorageRailsWorkhorseClientObject StorageRailsWorkhorseClientAppend `/authorize` to the original URL and call Rails for an Auth checkWorkhorse calls the original URL to create a database recordPUT /artifacts/uploadsGET /artifacts/uploads/authorizeAuthorized successfullyStream the file contentUpload the fileSuccessFinalize the requestFinalized successfullyUploaded successfully

Git over HTTP(S)

Workhorse accelerates Git over HTTP(S) by handling Git HTTP protocol requests. For example, Git push/pull may require serving large amounts of data and in order to avoid transferring it through GitLab Rails, Workhorse only performs authorization checks against GitLab Rails, then performs Gitaly gRPC request directly and streams the data from Gitaly to the Git client.

Git pull

GitalyRailsWorkhorseGit on clientGitalyRailsWorkhorseGit on clientgit clone/fetchAccess check/Log activityAccess check/Update statisticsGET /foo/bar.git/info/refs/?service=git-upload-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.InfoRefsUploadPack gRPC requestSmartHTTPService.InfoRefsUploadPack gRPC responsesend info-refs responseGET /foo/bar.git/info/refs/?service=git-upload-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.PostUploadPackWithSidechannel gRPC requestSmartHTTPService.PostUploadPackWithSidechannel gRPC responsesend response

Git push

GitalyRailsWorkhorseGit on clientGitalyRailsWorkhorseGit on clientgit pushAccess check/Log activityAccess check/Update statisticsGET /foo/bar.git/info/refs/?service=git-receive-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.InfoRefsReceivePack gRPC requestSmartHTTPService.InfoRefsReceivePack gRPC responsesend info-refs responseGET /foo/bar.git/info/refs/?service=git-receive-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.PostReceivePackWithSidechannel gRPC requestSmartHTTPService.PostReceivePackWithSidechannel gRPC responsesend response