Exemple utilisation httpwebrequest, afficher réponse http à une requête get post avec affichage redirections

Soyez le premier à donner votre avis sur cette source.

Vue 50 244 fois - Téléchargée 2 594 fois

Description

Ce programme permet d'envoyer des requêtes HTTP à un serveur Web, et de récupérer la réponse sous forme de texte dans un contrôle texte.
Il gère les redirections une à une. Chaque réponses de demande de redirection est affichée. Et la redirection est intérrogée automatiquement.
Les cookies sont aussi géré. Qu'ils proviennent de la réponse ou créés par l'utilisateur.
Tout échec de la requête, qui entraine une exception résulte dans l'affichage de celle-ci comme résultat de la requête.
On peut faire des requêtes GET et POST. Les données POST sont limitées à une ligne de texte.
Les nouvelles requêtes n'écrasent pas les anciennes, ainsi on peut utiliser le programme pour annalyser une série de requête/réponse entre le navigateur et le serveur afin d'automatiser un processus, ou de récupérer l'adresse d'une page de saut intermédiaire.
Le code n'étant pas commenté dans le fichier CS, je vais commenter la fonction de création, exécution de la requête dans la zone de code.

Source / Exemple :


private bool DoResquest(string URL, out string newURL)
{
	//Défini l'URL de destination de la redirection à vide. Car elle n'est définie que si il y a redirection.
	newURL = "";
	try
	{
		// Créer la requête HTTP.
		HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
		// Défini les champs de méthode, de type de navigateur, de types acceptés.
		req.Method = method.Text;
		req.UserAgent = useragent.Text;
		req.Accept = accept.Text;
		// Supprime le suivi de la redirection automatique.
		req.AllowAutoRedirect = false;
		// Défini les cookies, et si nécessaire, ajout le cookie utilisateur.
		req.CookieContainer = cookies;
		if (cookie.Text != "")
		{
			int signpos = cookie.Text.IndexOf("=");
			string cookiename = cookie.Text.Substring(0, signpos);
			string cookieval = cookie.Text.Substring(signpos + 1);
			req.CookieContainer.Add(new Cookie(cookiename, cookieval, "/", req.RequestUri.Host));
		}
		// Si la method est POST, alors il faut mettre les données dans le corps de la requête.
		if (method.Text == "POST")
		{
			string data = postdata.Text;
			// Définition des informations concernant le corps
			req.ContentLength = data.Length;
			req.ContentType = contenttype.Text;
			// Ecriture des données.
			Stream reqout = req.EndGetRequestStream(req.BeginGetRequestStream(new AsyncCallback(AsyncRequestWriter), null));
			StreamWriter wri = new StreamWriter(reqout, Encoding.GetEncoding(850));
			wri.Write(data);
			wri.Close();
			reqout.Close();
		}
		// Exécution de la requête.
		HttpWebResponse res = (HttpWebResponse)req.GetResponse();
		// Ajout des nouveaux cookies si présents.
		cookies.Add(res.Cookies);
		// Afficher les premières informations de la requête (Method, URL, Etat de réponse et en-têtes.
		result.Text += "---------------------------------------------------\r\n";
		result.Text += req.Method + " " + URL + "\r\n";
		result.Text += res.StatusCode + " - " + res.StatusDescription + "\r\n";
		result.Text += res.Headers.ToString() + "\r\n";
		// Suivant l'état. Redirection ou non.
		switch (res.StatusCode)
		{
			// Redirection normale.
			case HttpStatusCode.Redirect:
				method.SelectedIndex = 0;
				newURL = res.Headers.Get("Location");
				break;
			// Redirection gardant la methode.
			case HttpStatusCode.RedirectKeepVerb:
				newURL = res.Headers.Get("Location");
				break;
			// Redirection mettant la méthode à GET.
			case HttpStatusCode.RedirectMethod:
				method.SelectedIndex = 0;
				newURL = res.Headers.Get("Location");
				break;
			// Tout les autres état, nottament, OK
			default:
				// Affiche les données du flux
				Stream resin = res.GetResponseStream();
				StreamReader rea = new StreamReader(resin, Encoding.GetEncoding(850));
				result.Text += rea.ReadToEnd().Replace("\r\n", "\n").Replace("\n", "\r\n");
				rea.Close();
				resin.Close();
				break;
		}
		// Ferme la réponse
		res.Close();
		// Ferme la requête
		req.Close();
	}
	catch (Exception ex)
	{
		// Affiche l'exception dans la zone de résultat.
		result.Text += ex.ToString();
	}
	// Il y a redirection seulement si une adresse a été mise dans newURL.
	return newURL.Length != 0;
}

Conclusion :


Si vous trouvez le besoin de vouloir définir d'autres champs HTTP, celà peut se faire.
N'oubliez pas de lire les infos-bulles :)
Pour toutes questions, soit en commentaire, soit sur le chan C-S à MyGoddess (N'oubliez pas de préciser le sujet).

J'espère que ca pourra vous être utile.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

bonjour, j'aurai besoin de vous
je souhaite savoir qu'est-ce qu'il faut mettre dans le champs serveur?
Thanks
cs_CrazyBlade
Messages postés
2
Date d'inscription
mardi 17 mars 2009
Statut
Membre
Dernière intervention
28 février 2012

Merci !
cs_gipp
Messages postés
12
Date d'inscription
lundi 19 mars 2001
Statut
Membre
Dernière intervention
27 mai 2008

Un très grand merci pour ce code !
Tu m'as sauvé après 2 mois de galère !!!

Gilles
TeBeCo
Messages postés
467
Date d'inscription
lundi 24 juin 2002
Statut
Membre
Dernière intervention
9 mars 2011

Suite à l'utilisation de ce code j'ai apporté quelques modification qui pourront peut être résoudre quelques problème qui sont apparue chez moi :
Contexte : récupération de fichiers images au travers d'un formulaire de méthode "POST"

Premier problème : Le "rea.ReadToEnd()" lit les caractère issue de la réponse du serveur au travers d'un encoding type "Europe de l'ouest" :
StreamReader rea = new StreamReader(resin, Encoding.GetEncoding(850));
cela peux deja poser problème si l'encoding utilisé ne correspond pas a celui requis pour ce type de donnée car les image sont en format binaire peut importe l'encoding pour en faire des caractères.
Donc il faudrait dans ce cas présent tout simplement éviter de passer par un StreamReader qui quoi qu'il arrive fera TOUJOURS un décodage meme si vous n'en spécifier pas il prendra celui par default.
Je me suis donc attaquer directement au flux lui même :
Stream resin = res.GetResponseStream();
le problème qui se pose avec ce genre de flux est de detecté la taille des donnée à lire car il n'y a pas (ou alors pas vu) d'indicateur de fin de flux.
pour cela :
int TailleFichier = int.Parse(res.Headers.Get("Content-length"));
afin de récupérer la taille du fichier renvoyé par le serveur
A partir de la il faut reussir à lire les données suffisament vite car par exemple le serveur ou j'étais limite la durée de vie du stream à 30 secondes maximum une fois le delais impartit le flux est refermé.

J'ai utilisé (au début) une solution pas forcément optimale mais qui semble relativement bien marcher :

const int TaillePacket = 1024;
struct Packet {
public byte[] Data;
public int nbOctet;
}
System.Collection.Generic.Queue Fichier;

/* ... */

Stream resin = res.GetResponseStream();
int TailleFichier = int.Parse(res.Headers.Get("Content-length"));
int nbOctetRecu = 0;
Fichier = new System.Collection.Generic.Queue((TailleFichier + TaillePacket -1)/TaillePacket );
while(nbOctetRecu <= TailleFichier)
{
Packet PacketEnCour = new Packet();
PacketEnCour.Data = new byte[TaillePacket];
PacketEnCour.nbOctet = resin.Read(PacketEnCour.Data, 0, TaillePacket);
Fichier.Enqueue(PacketEnCour);
nbOctetRecu += PacketEnCour.nbOctet;
}

une fois fait il reste plus qu'à dépilé tout ca bétement
Packet tmp;
while(Fichier.Count > 0)
{
tmp = Fichier.Dequeue();
//traitement en prenant compte de la longueur des octets present dedans
}

pourquoi ne pas mettre le buffer de 1024 directement à la place d'une structure ?
pour une connexion relativement lente le serveur à pas le temps d'envoyer 1024 octet le temps d'une boucle de lecture resultat il y a moins que 1024 octet à prendre en compte au début on se demande pourquoi il envoi 51 paquets de 1K pour des image de 36K :p

sinon la version plus simple pour une image et nettement plus rapide :
Stream resin = res.GetResponseStream();
if(res.Headers.Get("Content-type").ToLower() == "image/jpeg".ToLower())
{
Image img = Image.FromStream(resin);
img.Save("C:\\monimage.jpg");
}

voila me suis dit que ca pourrais serveir à qq personne
BaFM
Messages postés
64
Date d'inscription
mercredi 24 juillet 2002
Statut
Membre
Dernière intervention
26 novembre 2009

Alors pour répondre simplement : ben ca fonctionne comme pour les navigateurs web...
Le paramètre passé à la dll, donc serveur IIS, c'est le nom de l'action à appeler.
Ensuite, il faut que tu fasse gaffe que tes données poste soit bien encodé comme si tu passais les informations par url. avec les '+' et les '%xx'.
Après qu'il ne résolve pas, c'est que tu doit avoir fait une erreur de saisie. Puisque je reconstruit l'url à partir des paramètres.
Afficher les 13 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.