Download raw body.
gotwebd: fix double Content-type
On Wed, Jul 27, 2022 at 11:13:04AM +0200, Omar Polo wrote:
> Hello,
>
> when rendering a blob, gotwebd prints the Content-Type header twice.
> Since gotweb_render_content_type_file also adds the empty line to
> terminate the headers part of the HTTP reply, the second Content-Type is
> sent as part of the blob.
>
> this arises from gotweb_process_request unconditionally setting the
> content type to text/plain while got_output_file_blob (called next)
> already does so.
>
> in got_output_file_blob there is also a typo in the content type:
> unfortunately "text/text" doesn't seem to exist, so change it to
> "text/plain".
>
> While here i couldn't help not to tweak to fcgi_gen{_binary,}_response,
> isbinary and to the last part of the loop in got_output_file_blob.
>
> I've noticed that fcgi_gen_response and the _binary variant are
> practically the same function, with the exception that fcgi_gen_response
> implicitly calls strlen and quits if the length is zero. So, why not
> dedup the code?
>
> I'm also adding a check in fcgi_gen_binary_response to bail out if len
> is zero, because got_output_file_blob may call it with a zero length and
> the other function had this optimization anyway.
>
> now, since fcgi_gen_binary_response and fcgi_gen_response are
> fundamentally the same function, i think we can simplify the last part
> of the loop in got_output_file_blob.
>
> the change to isbinary is just because i thought it would read better
> with a memchr and because it's shorter, but i'm fine with dropping it if
> the explicit loop is preferred.
>
> ---
>
> There is still another issue is gotwebd that I've found and still
> haven't tracked down. it doesn't dump all the blob somehow. Here's an
> example:
>
> https://git.omarpolo.com/?index_page=&path=amused.git&action=blob&commit=3fc7366684dd5a216deed3c8d7c69c1792022d5c&folder=&file=amused.c
>
Weird. Will look into this after you get this diff in. ok.
> the blob is always truncated at `main_send_player' and some gibberish is
> added at the end apparently. I'm running gotwebd from the latest commit
> in main as of now plus below diff applied, but this bug was there even
> without my diff.
>
> ---
>
> ok?
>
> diff /home/op/w/got
> commit - 615e455c6bdddbd4e59d5d0dece41eb9953b6336
> path + /home/op/w/got
> blob - 1581cf938674fc59b27476119bfcc54b5b4417b5
> file + gotwebd/fcgi.c
> --- gotwebd/fcgi.c
> +++ gotwebd/fcgi.c
> @@ -311,7 +311,7 @@ fcgi_gen_binary_response(struct request *c, const uint
> if (c->sock->client_status == CLIENT_DISCONNECT)
> return -1;
>
> - if (data == NULL)
> + if (data == NULL || len == 0)
> return 0;
>
> if ((resp = calloc(1, sizeof(struct fcgi_response))) == NULL) {
> @@ -342,43 +342,9 @@ fcgi_gen_binary_response(struct request *c, const uint
> int
> fcgi_gen_response(struct request *c, const char *data)
> {
> - struct fcgi_response *resp;
> - struct fcgi_record_header *header;
> - ssize_t n = 0;
> - int i;
> -
> - if (c->sock->client_status == CLIENT_DISCONNECT)
> - return -1;
> -
> - if (data == NULL)
> + if (data == NULL || *data == '\0')
> return 0;
> -
> - if (strlen(data) == 0)
> - return 0;
> -
> - if ((resp = calloc(1, sizeof(struct fcgi_response))) == NULL) {
> - log_warn("%s: cannot calloc fcgi_response", __func__);
> - return -1;
> - }
> -
> - header = (struct fcgi_record_header*) resp->data;
> - header->version = 1;
> - header->type = FCGI_STDOUT;
> - header->id = htons(c->id);
> - header->padding_len = 0;
> - header->reserved = 0;
> -
> - for (i = 0; i < strlen(data); i++) {
> - resp->data[i+8] = data[i];
> - n++;
> - }
> -
> - header->content_len = htons(n);
> - resp->data_pos = 0;
> - resp->data_len = n + sizeof(struct fcgi_record_header);
> - fcgi_send_response(c, resp);
> -
> - return 0;
> + return fcgi_gen_binary_response(c, data, strlen(data));
> }
>
> void
> blob - e8a77c36de8a9bb990ee17fc8764af9390f1915c
> file + gotwebd/got_operations.c
> --- gotwebd/got_operations.c
> +++ gotwebd/got_operations.c
> @@ -55,12 +55,7 @@ static const struct got_error *got_gotweb_blame_cb(voi
> static int
> isbinary(const uint8_t *buf, size_t n)
> {
> - size_t i;
> -
> - for (i = 0; i < n; i++)
> - if (buf[i] == 0)
> - return 1;
> - return 0;
> + return memchr(buf, '\0', n) != NULL;
> }
>
>
> @@ -1201,8 +1196,7 @@ got_output_file_blob(struct request *c)
> struct got_reflist_head refs;
> struct got_blob_object *blob = NULL;
> char *path = NULL, *in_repo_path = NULL;
> - int obj_type, set_mime = 0, type = 0, fd = -1;
> - char *buf_output = NULL;
> + int obj_type, set_mime = 0, fd = -1;
> size_t len, hdrlen;
> const uint8_t *buf;
>
> @@ -1274,32 +1268,18 @@ got_output_file_blob(struct request *c)
> error->msg);
> goto done;
> }
> - type = 0;
> } else {
> error = gotweb_render_content_type(c,
> - "text/text");
> + "text/plain");
> if (error) {
> log_warnx("%s: %s", __func__,
> error->msg);
> goto done;
> }
> - type = 1;
> }
> }
> set_mime = 1;
> - if (type) {
> - buf_output = calloc(len - hdrlen + 1,
> - sizeof(*buf_output));
> - if (buf_output == NULL) {
> - error = got_error_from_errno("calloc");
> - goto done;
> - }
> - memcpy(buf_output, buf, len - hdrlen);
> - fcgi_gen_response(c, buf_output);
> - free(buf_output);
> - buf_output = NULL;
> - } else
> - fcgi_gen_binary_response(c, buf, len - hdrlen);
> + fcgi_gen_binary_response(c, buf, len - hdrlen);
>
> hdrlen = 0;
> } while (len != 0);
> @@ -1310,7 +1290,6 @@ done:
> error = got_error_from_errno("close");
> if (blob)
> got_object_blob_close(blob);
> - free(buf_output);
> free(in_repo_path);
> free(commit_id);
> free(path);
> blob - c30fdedd0e6b808f3a0607b931d83f55c2e7b317
> file + gotwebd/gotweb.c
> --- gotwebd/gotweb.c
> +++ gotwebd/gotweb.c
> @@ -177,11 +177,6 @@ gotweb_process_request(struct request *c)
> error = got_get_repo_commits(c, 1);
> if (error)
> goto done;
> - error = gotweb_render_content_type(c, "text/plain");
> - if (error) {
> - log_warnx("%s: %s", __func__, error->msg);
> - goto err;
> - }
> error = got_output_file_blob(c);
> if (error) {
> log_warnx("%s: %s", __func__, error->msg);
>
--
Tracey Emery
gotwebd: fix double Content-type