264
274
proxySelector = ProxySelector.GetDefault();
277
/// <summary>Create a minimal HTTP transport with default configuration values.</summary>
278
/// <remarks>Create a minimal HTTP transport with default configuration values.</remarks>
279
/// <param name="uri"></param>
280
/// <exception cref="System.NotSupportedException">System.NotSupportedException</exception>
281
protected internal TransportHttp(URIish uri) : base(uri)
285
string uriString = uri.ToString();
286
if (!uriString.EndsWith("/"))
292
baseUrl = new Uri(uriString);
293
objectsUrl = new Uri(baseUrl, "objects/");
295
catch (UriFormatException e)
298
throw new NGit.Errors.NotSupportedException(MessageFormat.Format(JGitText.Get().invalidURL, uri
301
http = new TransportHttp.HttpConfig();
302
proxySelector = ProxySelector.GetDefault();
267
305
/// <summary>Toggle whether or not smart HTTP transport should be used.</summary>
269
307
/// Toggle whether or not smart HTTP transport should be used.
918
962
protected internal override void DoPush(ProgressMonitor monitor, IDictionary<string
919
963
, RemoteRefUpdate> refUpdates)
921
TransportHttp.Service svc = new TransportHttp.Service(_enclosing, TransportHttp.SVC_RECEIVE_PACK
923
this.Init(svc.@in, svc.@out);
965
TransportHttp.Service svc = new TransportHttp.MultiRequestService(_enclosing, TransportHttp
967
this.Init(svc.GetInputStream(), svc.GetOutputStream());
924
968
base.DoPush(monitor, refUpdates);
927
971
private readonly TransportHttp _enclosing;
930
/// <summary>State required to speak multiple HTTP requests with the remote.</summary>
932
/// State required to speak multiple HTTP requests with the remote.
934
/// A service wrapper provides a normal looking InputStream and OutputStream
935
/// pair which are connected via HTTP to the named remote service. Writing to
936
/// the OutputStream is buffered until either the buffer overflows, or
937
/// reading from the InputStream occurs. If overflow occurs HTTP/1.1 and its
938
/// chunked transfer encoding is used to stream the request data to the
939
/// remote service. If the entire request fits in the memory buffer, the
940
/// older HTTP/1.0 standard and a fixed content length is used instead.
942
/// It is an error to attempt to read without there being outstanding data
943
/// ready for transmission on the OutputStream.
945
/// No state is preserved between write-read request pairs. The caller is
946
/// responsible for replaying state vector information as part of the request
947
/// data written to the OutputStream. Any session HTTP cookies may or may not
948
/// be preserved between requests, it is left up to the JVM's implementation
949
/// of the HTTP client.
951
internal class Service
974
/// <summary>Basic service for sending and receiving HTTP requests.</summary>
975
/// <remarks>Basic service for sending and receiving HTTP requests.</remarks>
976
internal abstract class Service
953
private readonly string serviceName;
955
private readonly string requestType;
957
private readonly string responseType;
959
private readonly TransportHttp.Service.HttpExecuteStream execute;
961
internal bool finalRequest;
978
protected internal readonly string serviceName;
980
protected internal readonly string requestType;
982
protected internal readonly string responseType;
984
protected internal HttpURLConnection conn;
986
protected internal TransportHttp.Service.HttpOutputStream @out;
988
protected internal readonly TransportHttp.Service.HttpExecuteStream execute;
963
990
internal readonly UnionInputStream @in;
965
internal readonly TransportHttp.Service.HttpOutputStream @out;
967
internal HttpURLConnection conn;
969
992
internal Service(TransportHttp _enclosing, string serviceName)
971
994
this._enclosing = _enclosing;
993
1016
/// <exception cref="System.IO.IOException"></exception>
994
internal virtual void Execute()
1017
internal virtual void SendRequest()
997
if (this.conn == null)
999
if (this.@out.Length() == 0)
1001
// Request output hasn't started yet, but more data is being
1002
// requested. If there is no request data buffered and the
1003
// final request was already sent, do nothing to ensure the
1004
// caller is shown EOF on the InputStream; otherwise an
1005
// programming error has occurred within this module.
1006
if (this.finalRequest)
1010
throw new TransportException(this._enclosing.uri, JGitText.Get().startingReadStageWithoutWrittenRequestDataPendingIsNotSupported
1013
1019
// Try to compress the content, but only if that is smaller.
1014
1020
TemporaryBuffer buf = new TemporaryBuffer.Heap(this._enclosing.http.postBuffer);
1059
1068
this.conn.GetInputStream().Close();
1060
1069
throw this._enclosing.WrongContentType(this.responseType, contentType);
1062
this.@in.Add(this._enclosing.OpenInputStream(this.conn));
1063
if (!this.finalRequest)
1065
this.@in.Add(this.execute);
1073
internal virtual TransportHttp.Service.HttpOutputStream GetOutputStream()
1078
internal virtual InputStream GetInputStream()
1083
/// <exception cref="System.IO.IOException"></exception>
1084
internal abstract void Execute();
1086
internal class HttpExecuteStream : InputStream
1088
/// <exception cref="System.IO.IOException"></exception>
1089
public override int Read()
1091
this._enclosing.Execute();
1095
/// <exception cref="System.IO.IOException"></exception>
1096
public override int Read(byte[] b, int off, int len)
1098
this._enclosing.Execute();
1102
/// <exception cref="System.IO.IOException"></exception>
1103
public override long Skip(long n)
1105
this._enclosing.Execute();
1109
internal HttpExecuteStream(Service _enclosing)
1111
this._enclosing = _enclosing;
1114
private readonly Service _enclosing;
1070
1117
internal class HttpOutputStream : TemporaryBuffer
1086
1133
private readonly Service _enclosing;
1089
internal class HttpExecuteStream : InputStream
1091
/// <exception cref="System.IO.IOException"></exception>
1092
public override int Read()
1094
this._enclosing.Execute();
1098
/// <exception cref="System.IO.IOException"></exception>
1099
public override int Read(byte[] b, int off, int len)
1101
this._enclosing.Execute();
1105
/// <exception cref="System.IO.IOException"></exception>
1106
public override long Skip(long n)
1108
this._enclosing.Execute();
1112
internal HttpExecuteStream(Service _enclosing)
1114
this._enclosing = _enclosing;
1117
private readonly Service _enclosing;
1136
private readonly TransportHttp _enclosing;
1139
/// <summary>State required to speak multiple HTTP requests with the remote.</summary>
1141
/// State required to speak multiple HTTP requests with the remote.
1143
/// A service wrapper provides a normal looking InputStream and OutputStream
1144
/// pair which are connected via HTTP to the named remote service. Writing to
1145
/// the OutputStream is buffered until either the buffer overflows, or
1146
/// reading from the InputStream occurs. If overflow occurs HTTP/1.1 and its
1147
/// chunked transfer encoding is used to stream the request data to the
1148
/// remote service. If the entire request fits in the memory buffer, the
1149
/// older HTTP/1.0 standard and a fixed content length is used instead.
1151
/// It is an error to attempt to read without there being outstanding data
1152
/// ready for transmission on the OutputStream.
1154
/// No state is preserved between write-read request pairs. The caller is
1155
/// responsible for replaying state vector information as part of the request
1156
/// data written to the OutputStream. Any session HTTP cookies may or may not
1157
/// be preserved between requests, it is left up to the JVM's implementation
1158
/// of the HTTP client.
1160
internal class MultiRequestService : TransportHttp.Service
1162
internal bool finalRequest;
1164
internal MultiRequestService(TransportHttp _enclosing, string serviceName) : base
1165
(_enclosing, serviceName)
1167
this._enclosing = _enclosing;
1170
/// <summary>Keep opening send-receive pairs to the given URI.</summary>
1171
/// <remarks>Keep opening send-receive pairs to the given URI.</remarks>
1172
/// <exception cref="System.IO.IOException"></exception>
1173
internal override void Execute()
1176
if (this.conn == null)
1178
if (this.@out.Length() == 0)
1180
// Request output hasn't started yet, but more data is being
1181
// requested. If there is no request data buffered and the
1182
// final request was already sent, do nothing to ensure the
1183
// caller is shown EOF on the InputStream; otherwise an
1184
// programming error has occurred within this module.
1185
if (this.finalRequest)
1189
throw new TransportException(this._enclosing.uri, JGitText.Get().startingReadStageWithoutWrittenRequestDataPendingIsNotSupported
1195
this.OpenResponse();
1196
this.@in.Add(this._enclosing.OpenInputStream(this.conn));
1197
if (!this.finalRequest)
1199
this.@in.Add(this.execute);
1204
private readonly TransportHttp _enclosing;
1207
/// <summary>Service for maintaining a single long-poll connection.</summary>
1208
/// <remarks>Service for maintaining a single long-poll connection.</remarks>
1209
internal class LongPollService : TransportHttp.Service
1211
/// <param name="serviceName"></param>
1212
internal LongPollService(TransportHttp _enclosing, string serviceName) : base(_enclosing, serviceName
1215
this._enclosing = _enclosing;
1218
/// <summary>Only open one send-receive request.</summary>
1219
/// <remarks>Only open one send-receive request.</remarks>
1220
/// <exception cref="System.IO.IOException"></exception>
1221
internal override void Execute()
1224
if (this.conn == null)
1228
this.OpenResponse();
1229
this.@in.Add(this._enclosing.OpenInputStream(this.conn));
1120
1232
private readonly TransportHttp _enclosing;