@@ -82,7 +82,8 @@ struct git_http_client {
8282
8383 unsigned request_count ;
8484 unsigned connected : 1 ,
85- keepalive : 1 ;
85+ keepalive : 1 ,
86+ request_chunked : 1 ;
8687
8788 /* Temporary buffers to avoid extra mallocs */
8889 git_buf request_msg ;
@@ -587,6 +588,7 @@ int git_http_client_send_request(
587588 client -> state = SENDING_BODY ;
588589 client -> request_body_len = request -> content_length ;
589590 client -> request_body_remain = request -> content_length ;
591+ client -> request_chunked = request -> chunked ;
590592 } else {
591593 client -> state = SENT_REQUEST ;
592594 }
@@ -600,15 +602,49 @@ int git_http_client_send_body(
600602 const char * buffer ,
601603 size_t buffer_len )
602604{
605+ git_http_server * server ;
606+ git_buf hdr = GIT_BUF_INIT ;
603607 int error ;
604608
605609 assert (client && client -> state == SENDING_BODY );
606- assert (buffer_len <= client -> request_body_remain );
607610
608- error = stream_write (& client -> server , buffer , buffer_len );
611+ if (!buffer_len )
612+ return 0 ;
613+
614+ server = & client -> server ;
615+
616+ if (client -> request_body_len ) {
617+ assert (buffer_len <= client -> request_body_remain );
618+
619+ if ((error = stream_write (server , buffer , buffer_len )) < 0 )
620+ goto done ;
609621
610- if (error == 0 )
611622 client -> request_body_remain -= buffer_len ;
623+ } else {
624+ if ((error = git_buf_printf (& hdr , "%" PRIxZ "\r\n" , buffer_len )) < 0 ||
625+ (error = stream_write (server , hdr .ptr , hdr .size )) < 0 ||
626+ (error = stream_write (server , buffer , buffer_len )) < 0 ||
627+ (error = stream_write (server , "\r\n" , 2 )) < 0 )
628+ goto done ;
629+ }
630+
631+ done :
632+ git_buf_dispose (& hdr );
633+ return error ;
634+ }
635+
636+ static int complete_request (git_http_client * client )
637+ {
638+ int error = 0 ;
639+
640+ assert (client && client -> state == SENDING_BODY );
641+
642+ if (client -> request_body_len && client -> request_body_remain ) {
643+ git_error_set (GIT_ERROR_NET , "truncated write" );
644+ error = -1 ;
645+ } else if (client -> request_chunked ) {
646+ error = stream_write (& client -> server , "0\r\n\r\n" , 5 );
647+ }
612648
613649 return error ;
614650}
@@ -758,15 +794,12 @@ int git_http_client_read_response(
758794 assert (response && client );
759795
760796 if (client -> state == SENDING_BODY ) {
761- if (client -> request_body_len && client -> request_body_remain ) {
762- git_error_set (GIT_ERROR_NET , "truncated write" );
763- return -1 ;
764- }
765-
766- client -> state = SENT_REQUEST ;
797+ if ((error = complete_request (client )) < 0 )
798+ goto done ;
767799 } else if (client -> state != SENT_REQUEST ) {
768800 git_error_set (GIT_ERROR_NET , "client is in invalid state" );
769- return -1 ;
801+ error = -1 ;
802+ goto done ;
770803 }
771804
772805 client -> state = READING_RESPONSE ;
0 commit comments