Apache HTTPClient Streaming Requête HTTP POST?
Je suis en train de construire un "full-duplex" HTTP streaming demande l'aide de Apache HTTPClient.
Dans ma première tentative, j'ai essayé d'utiliser la requête suivante de code:
URL url=new URL(/* code goes here */);
HttpPost request=new HttpPost(url.toString());
request.addHeader("Connection", "close");
PipedOutputStream requestOutput=new PipedOutputStream();
PipedInputStream requestInput=new PipedInputStream(requestOutput, DEFAULT_PIPE_SIZE);
ContentType requestContentType=getContentType();
InputStreamEntity requestEntity=new InputStreamEntity(requestInput, -1, requestContentType);
request.setEntity(requestEntity);
HttpEntity responseEntity=null;
HttpResponse response=getHttpClient().execute(request); //<-- Hanging here
try {
if(response.getStatusLine().getStatusCode() != 200)
throw new IOException("Unexpected status code: "+response.getStatusLine().getStatusCode());
responseEntity = response.getEntity();
}
finally {
if(responseEntity == null)
request.abort();
}
InputStream responseInput=responseEntity.getContent();
ContentType responseContentType;
if(responseEntity.getContentType() != null)
responseContentType = ContentType.parse(responseEntity.getContentType().getValue());
else
responseContentType = DEFAULT_CONTENT_TYPE;
Reader responseStream=decode(responseInput, responseContentType);
Writer requestStream=encode(requestOutput, getContentType());
La demande se bloque à la ligne indiquée ci-dessus. Il semble que le code est d'essayer d'envoyer la totalité de la demande avant qu'il obtient la réponse. Rétrospectivement, cela fait sens. Cependant, ce n'est pas ce que j'espérais. 🙂
Au lieu de cela, j'ai été en espérant pour envoyer les en-têtes de demande Transfer-Encoding: chunked
, de recevoir une réponse de l'en-tête de HTTP/1.1 200 OK
avec un Transfer-Encoding: chunked
en-tête de son propre, puis j'aurais un full-duplex streaming connexion HTTP à travailler avec.
Heureusement, mes HTTPClient a un autre NIO asynchrone basé sur des clients avec de bons exemples d'utilisation (comme cette une). Mes questions sont les suivantes:
- Est mon interprétation de la machine synchrone HTTPClient comportement correct? Ou est-il quelque chose que je peux faire pour continuer à utiliser le (plus simple) synchrone HTTPClient de la manière que j'ai décrite?
- Ne le NIO client basé sur attendre pour envoyer la totalité de la requête avant de chercher une réponse? Ou vais-je être en mesure d'envoyer la demande de façon progressive et recevoir la réponse progressivement en même temps?
Si HTTPClient ne soutiendra pas cette modalité, est-il un autre client HTTP bibliothèque? Ou devrais-je avoir l'intention d'écrire un (minimum) à l'adresse du client à l'appui de cette modalité?
OriginalL'auteur sigpwned | 2013-06-09
Vous devez vous connecter pour publier un commentaire.
Voici mon point de vue sur écrémé lecture du code:
Je ne peux pas complètement d'accord avec le fait qu'une non-réponse de 200 signifie l'échec. Toutes les réponses 2XX sont pour la plupart valide. Vérifier wiki pour plus de détails
Pour toute demande TCP, je le recommande à recevoir la totalité de la réponse de confirmer qu'il est valide. Je dis cela parce que, une réponse partielle peut généralement être traitée comme une mauvaise réponse comme la plupart des implémentations du client ne peut en faire usage. (Imaginer un cas où le serveur répond avec 2 mo de données et elle descend pendant ce temps)
Ce ne sont pas la raison pour laquelle le programme se bloque. C'est en raison de canalisations du flux d'entrée.
OriginalL'auteur Chris
Note: il me Semble que, depuis les canalisations de ruisseaux et de la concurrence n'étaient pas mentionnées dans votre énoncé du problème, qu'il n'est pas nécessaire. Essayez d'emballer un ByteArrayInputStream() avec l'Entité de l'objet à la place d'abord pour une vérification générale... qui devrait vous aider à cerner le problème.
Mise à jour
D'ailleurs, j'ai écrit une inversion de Apache HTTP du Client API [PipedApacheClientOutputStream] qui fournit un OutputStream interface pour HTTP POST à l'aide d'Apache Commons HTTP Client 4.3.4. Cela peut être proche de ce que vous cherchez...
Appel, le code ressemble à ceci:
Note - Dans la pratique, le même client, de l'exécuteur testamentaire de service, et la configuration susceptible d'être réutilisé tout au long de la vie de l'application, de sorte que l'extérieur de la prep et à proximité de code dans l'exemple ci-dessus va probablement vivre dans le bootstrap/init et la finalisation du code plutôt que directement en ligne avec le OutputStream de l'instanciation.
OriginalL'auteur Robert Christian