//Interception de reqêtes http en Java /* EtudeHttp.java interception de requêtes/réponses Http http://127.0.0.1:8383/ http://129.175.248.2/ ou www.iut-orsay.fr Application qui est à la fois serveur Http - classe MonServeur -, (écoute sur le port 8383), et client Http (voir la méthode envoieRqt - classe ReponseHttp - pour l'envoi d'une requête et récupération de la réponse) classes EtudeHttp extends Frame interface utilisateur TxtFen les chaînes à afficher RqtRepHttp informations d'une requête ou une réponse RfxEnregistreCorps réflexe pour enregistrer le corps d'une réponse RfxEnvoieRequete réflexe pour envoyer une requête MonServeur extends Thread processus léger, un serveur MonServeurF extends MonServeur lien avec fenêtre ReponseHttp extends Thread processus léger, réponse du serveur ReponseHttpF extends ReponseHtt lien avec fenêtrep */ import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import java.util.GregorianCalendar; import java.util.Calendar; // public class EtudeHttp extends JFrame { public class EtudeHttp extends Frame { static final int portEcouteServeur=8383; final int CLIENT = 0, SERVEUR = 1; int cliOuSer=0; // clinet ou serfvuer (cf affRqtRep, RfxEnregistrerCorps) TxtFen txtFen[]; // champs titfen,titrqt,rqt.prem,rqt.entete,rqt.corps, // titrep,rep.prem,rep.entete,rep.corps final int nCarLigne=50; // nb.caractères par ligne // Composants d'interface utilisateur Label e_titfen = new Label(); Label e_qqinfo = new Label(); Label e_separateur = new Label(); // Panneau de gauche concerne une requête Panel p_requete = new Panel(); Label e_titrqt = new Label(); Label e_cmd = new Label(); TextField c_cmd = new TextField(nCarLigne-5); //U Label e_entrqt = new Label(); TextArea t_entrqt = new TextArea(7,nCarLigne); //U Label e_corrqt = new Label(); TextArea t_corrqt = new TextArea(5,nCarLigne); //U Panel p_macport = new Panel(); Label e_machine = new Label(); TextField c_machine = new TextField(13); //U Label e_espace = new Label(); Label e_port = new Label(); TextField c_port = new TextField(4); //U Button b_rqtClient = new Button(); // Panneau de droite concerne une réponse Panel p_reponse = new Panel(); Label e_titrep = new Label(); Label e_etat = new Label(); TextField c_etat = new TextField(nCarLigne-5); //U Label e_entrep = new Label(); TextArea t_entrep = new TextArea(7,nCarLigne); //U Label e_correp = new Label(); TextArea t_correp = new TextArea(5,nCarLigne); //U Panel p_inutile = new Panel(); Label e_ficHtml = new Label(); TextField c_ficHtml = new TextField(10); //U Button b_ficHtml = new Button(); public EtudeHttp() throws Exception { txtFen = new TxtFen[] { new TxtFen("Je suis CLIENT", "Requête à envoyer", "Réponse reçue", "Envoyer la requête"), new TxtFen("Je suis SERVEUR", "Requête reçue", "Réponse envoyée", "Etre client") }; jbInit(); // On commence client affRqtRep(CLIENT); } /** Affiche requête et réponse placées dans txtFen[] * * @param cliser indique CLIENT ou SERVEUR */ void affRqtRep(int cliser) { this.cliOuSer = (cliser==CLIENT) ? CLIENT : SERVEUR; if(cliser==CLIENT || cliser==SERVEUR) e_titfen.setText(txtFen[cliser].titfen); else { cliser--; e_titfen.setText("Je suis PASSERELLE"); } e_titrqt.setText(txtFen[cliser].titrqt); c_cmd.setText(txtFen[cliser].rqt.prem); c_cmd.setEditable(cliser==CLIENT); t_entrqt.setText(txtFen[cliser].rqt.entete); t_entrqt.setEditable(cliser==CLIENT); t_corrqt.setText(new String(txtFen[cliser].rqt.corps)); t_corrqt.setEditable(cliser==CLIENT); c_machine.setText(txtFen[cliser].machine); c_port.setText(txtFen[cliser].port); boolean vis = (cliser == CLIENT); e_machine.setVisible(vis); c_machine.setVisible(vis); e_port.setVisible(vis); c_port.setVisible(vis); b_rqtClient.setLabel(txtFen[cliser].rqtClient); // A doite la réponse e_titrep.setText(txtFen[cliser].titrep); this.c_etat.setText(txtFen[cliser].rep.prem); this.t_entrep.setText(txtFen[cliser].rep.entete); boolean estTexte = txtFen[cliser].rep.typeCorps.indexOf("text") >= 0; if(estTexte) this.t_correp.setText(new String(txtFen[cliser].rep.corps)); else this.t_correp.setText( ""+txtFen[cliser].rep.corps.length+ " de type "+txtFen[cliser].rep.typeCorps); this.e_qqinfo.setText(txtFen[cliser].qqinfo); } // Construction de l'interface utilisateur private void jbInit() throws Exception { // this.getContentPane().setLayout(new BorderLayout()); this.setLayout(new BorderLayout()); e_titfen.setAlignment(Label.CENTER); e_titfen.setFont(new java.awt.Font("Dialog", 1, 12)); e_titfen.setText(txtFen[CLIENT].titfen); // this.getContentPane().add(e_titfen, BorderLayout.NORTH); this.add(e_titfen, BorderLayout.NORTH); e_qqinfo.setAlignment(Label.CENTER); e_qqinfo.setForeground(Color.red); e_qqinfo.setFont(new java.awt.Font("Dialog", 1, 12)); e_qqinfo.setText("- - - - -"); // this.getContentPane().add(e_qqinfo, BorderLayout.SOUTH); this.add(e_qqinfo, BorderLayout.SOUTH); e_separateur.setBackground(Color.gray); e_separateur.setText("|"); // this.getContentPane().add(e_separateur, BorderLayout.CENTER); this.add(e_separateur, BorderLayout.CENTER); // Coté requête this.add(p_requete, BorderLayout.WEST); GridBagLayout gridBagLayout1 = new GridBagLayout(); p_requete.setLayout(gridBagLayout1); p_requete.setBackground(Color.lightGray); p_requete.setSize(321, 654); e_titrqt.setAlignment(Label.CENTER); e_titrqt.setFont(new java.awt.Font("Dialog", 1, 12)); ajouter(p_requete, e_titrqt, 0,HORI); // Commande e_cmd.setText("commande"); ajouter(p_requete, e_cmd, 1,HORI); c_cmd.setFont(new java.awt.Font("Dialog", 1, 12)); ajouter(p_requete, c_cmd, 2,CENTRE); // En-tête de la requête e_entrqt.setText("en-tête"); ajouter(p_requete, e_entrqt, 3,HORI); t_entrqt.setFont(new java.awt.Font("Dialog", 1, 12)); t_entrqt.setForeground(Color.green);ajouter(p_requete,t_entrqt,4,CENTRE); e_corrqt.setText("corps"); ajouter(p_requete, e_corrqt, 5,HORI); // Corps de la requête GridBagConstraints c = new GridBagConstraints(); c.gridy=6; c.weighty=1.0; c.fill=GridBagConstraints.VERTICAL; ajouter(p_requete, t_corrqt, c); // Barre du bas p_macport.setLayout(new FlowLayout()); e_machine.setAlignment(Label.RIGHT); e_machine.setText("machine"); p_macport.add(e_machine, null); // c_machine.setText("www.iut-orsay.fr"); p_macport.add(c_machine, null); // e_espace.setText(" : "); p_macport.add(e_espace, null); e_port.setAlignment(Label.RIGHT); e_port.setText("port"); p_macport.add(e_port, null); // c_port.setText("8380"); p_macport.add(c_port, null); b_rqtClient.setFont(new java.awt.Font("Dialog", 1, 12)); p_macport.add(b_rqtClient); ajouter(p_requete, p_macport, 7,CENTRE); // Coté réponse this.add(p_reponse, BorderLayout.EAST); p_reponse.setBackground(Color.lightGray); p_reponse.setLayout(new GridBagLayout()); p_reponse.setSize(321, 654); e_titrep.setAlignment(Label.CENTER); e_titrep.setFont(new java.awt.Font("Dialog", 1, 12)); e_titrep.setText(txtFen[CLIENT].titrep); ajouter(p_reponse, e_titrep, 0,HORI); // Etat de la réponse e_etat.setText("état"); ajouter(p_reponse, e_etat, 1,HORI); c_etat.setFont(new java.awt.Font("Dialog", 1, 12)); c_etat.setText("Http/1.0 200 OK"); c_etat.setEditable(false); ajouter(p_reponse, c_etat, 2,CENTRE); // Entête de la réponse e_entrep.setText("en-tête"); ajouter(p_reponse, e_entrep, 3,HORI); t_entrep.setFont(new java.awt.Font("Dialog", 1, 12)); t_entrep.setForeground(Color.blue); t_entrep.setEditable(false); ajouter(p_reponse, t_entrep, 4,CENTRE); // Corps de la réponse e_correp.setText("corps"); ajouter(p_reponse, e_correp, 5,HORI); t_correp.setEditable(false); c.gridy=6; c.weighty=1.0; c.fill=GridBagConstraints.VERTICAL; ajouter(p_reponse, t_correp, c); // Barre du bas e_ficHtml.setText("fichier Html"); e_ficHtml.setAlignment(Label.RIGHT); p_inutile.add(e_ficHtml); c_ficHtml.setText("tmp.html"); p_inutile.add(c_ficHtml); b_ficHtml.setLabel("Enregistrer le corps"); b_ficHtml.setFont(new java.awt.Font("Dialog", 1, 12)); p_inutile.add(b_ficHtml); ajouter(p_reponse, p_inutile, 7,CENTRE); // Gestion des évènements b_rqtClient.addActionListener(new RfxEnvoieRequete(this)); this.b_ficHtml.addActionListener(new RfxEnregistreCorps(this)); WindowAdapter objf = new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }; this.addWindowListener(objf); } // fin jbinit() // void fenServeur(RqtRepHttp rqt,RqtRepHttp rep) {} void ajouter(Container p, Component og, GridBagConstraints c) { p.add(og,c); } void ajouter(Container p, Component og, int y, int remplir) { GridBagConstraints c = new GridBagConstraints(); c.gridx=0; c.gridy=y; c.fill=remplir; p.add(og,c); } // Des utilitaires static void a( String txt) {System.out.print(txt);} static void a_( String txt) {System.out.println(txt);} static void a( String txt, Exception e) { a_("\n"+txt); if( e != null) { // a_(" --> "+e.getLocalizedMessage()); // message court a_(" --> " + e.toString()); // e.printStackTrace(); // trace des appels } } static String date() { String mois[]={"janvier","février","mars","avril","mai","juin" ,"juillet","août","septembre","octbre","novembre","décembre"}; GregorianCalendar cal = new GregorianCalendar(); String hms=""+cal.get(Calendar.HOUR); int m=cal.get(Calendar.MINUTE), s=cal.get(Calendar.SECOND); hms=hms+":"; if( m<10) hms=hms+"0"; hms=hms+m+":"; if( s<10) hms=hms+"0"; hms=hms+s; return "" + cal.get(Calendar.DAY_OF_MONTH)+' ' + mois[cal.get(Calendar.MONTH)]+' ' + cal.get(Calendar.YEAR)+", "+hms; } public static void main(String[] args) { try { EtudeHttp fen = new EtudeHttp(); fen.setSize(new Dimension(700, 450)); fen.setLocation(50, 50); // fen.validate(); fen.pack(); System.out.println ("larg:" + fen.getSize().getWidth() + " haut:" + fen.getSize().getHeight()); fen.setVisible(true); MonServeur serveur= new MonServeurF(portEcouteServeur,fen); } catch (Exception e) { e.printStackTrace(); } } final int NORD=GridBagConstraints.NORTH; final int SUD=GridBagConstraints.SOUTH; final int EST=GridBagConstraints.EAST; final int OUEST=GridBagConstraints.WEST; final int CENTRE=GridBagConstraints.CENTER; final int VIDE=GridBagConstraints.NONE; final int HORI=GridBagConstraints.HORIZONTAL; final int VERT=GridBagConstraints.VERTICAL; } // Fin class EtudeHttp extends Frame class TxtFen { String titfen; String titrqt; String titrep; String machine, port, rqtClient; String qqinfo; // pour barre d'état en bas TxtFen(String f,String q,String p, String r) { titfen=f; titrqt=q; titrep=p; rqtClient=r; qqinfo=""; rqt = new RqtRepHttp(); rep = new RqtRepHttp(); } RqtRepHttp rqt, rep; } // Requête ou réponse Http class RqtRepHttp { String prem; // première ligne: commande ou état String entete; // pas de double R/C; terminé par un seul R/C byte corps[]; // terminé par un R/C String typeCorps; String msg; RqtRepHttp() {prem=entete=msg="";corps="".getBytes();typeCorps="text/html";} /** Vérifie la commande (rajoute éventuellement le protocole) Enlève lignes vides dans l'en-tête */ String norme() { String txtErr="", lesMots[]= new String[4]; char ch[]= prem.trim().toCharArray(); int n=ch.length, adeb,a,b, nbm=0; // Enlever les espaces excédentaires de la commande for(adeb=0, a=b=1; b<n; b++) { boolean carEsp; carEsp=Character.isSpaceChar(ch[b]); // espace en b if( carEsp && Character.isSpaceChar(ch[b-1])) ; else { if(carEsp && nbm<lesMots.length) { // un mot de plus lesMots[nbm] = new String(ch, adeb, a-adeb); nbm++; adeb=a+1; } ch[a]=ch[b]; a++ ; } } // On crée la commande avec au plus trois mots prem=""; if(n==0) txtErr="Commmande vide"; else { // dernier mot if(nbm<lesMots.length){lesMots[nbm]=new String(ch,adeb,a-adeb);nbm++;} prem=lesMots[0].toUpperCase(); if(nbm<2) txtErr="Commmande incomplète"; else { prem = prem+" "+lesMots[1]; if(nbm<3) prem = prem+" "+"HTTP/1.0"; else { prem = prem + " " + lesMots[2].toUpperCase(); if(nbm>3) txtErr="Trop de mots dans la commande"; } } } // EtudeHttp.a_("norme(), "+nbm+" mots '"+prem+"'"); // Enlever les lignes vides dans l'en-tête (2 \n consécutifs) // (retours chariots excédentaires) ch=entete.trim().toCharArray(); // ch ne termmine pas \n n=ch.length; for(a=b=1; b<n; b++) { if(ch[b-1]!='\n' || ch[b]!='\n') {ch[a]=ch[b]; a++ ; } } entete = (n>0) ? (new String(ch,0,a))+"\n" : ""; // Corps vide ou terminé par un seul '/n' corps = (new String(corps)).trim().getBytes(); return txtErr; } // fin norme() } // fin class RqtRepHttp /** Enregistre le corps d'une réponse dans un fichier */ class RfxEnregistreCorps implements ActionListener { EtudeHttp fen; RfxEnregistreCorps(EtudeHttp f) { fen = f; } public void actionPerformed(ActionEvent e) { String nfic=fen.c_ficHtml.getText(); File f= new File(fen.c_ficHtml.getText()); try { FileOutputStream fic=new FileOutputStream(f); fic.write(fen.txtFen[fen.cliOuSer].rep.corps); fic.close(); } catch(IOException ex){ fen.e_qqinfo.setText("pb avec fichier "+nfic); EtudeHttp.a("RfxEnregistreCorps, fichier ",ex); } } } /** Envoie la requête tapée dans l'état 'Je suis CLIENT', récupère et affiche * le résultat. */ class RfxEnvoieRequete implements ActionListener { EtudeHttp fen; RfxEnvoieRequete(EtudeHttp f) {fen=f; } public void actionPerformed(ActionEvent e) { TxtFen tF=fen.txtFen[fen.CLIENT]; tF.qqinfo = ""; tF.rqt=new RqtRepHttp(); tF.rep=new RqtRepHttp(); Button b=(Button)e.getSource(); if(b.getLabel().equals(fen.txtFen[fen.CLIENT].rqtClient)) { // On récupère commande, en-tête et corps; tF.rqt.prem = fen.c_cmd.getText(); tF.rqt.entete = fen.t_entrqt.getText(); tF.rqt.corps = fen.t_corrqt.getText().getBytes(); tF.qqinfo = tF.rqt.norme(); // On récupère machine et port String machine=fen.c_machine.getText(); String ch_port=fen.c_port.getText(); tF.machine = machine; int port=0; tF.port = ch_port; try { port=Integer.parseInt(ch_port); } catch(Exception exc) { tF.qqinfo = tF.qqinfo + " | numéro de port incorrect: "+ch_port; } // Envoie effectif et affichages if(tF.qqinfo.length() == 0) { tF.rep = ReponseHttp.envoieRqt( machine, port, tF.rqt); tF.qqinfo = tF.rep.msg; // EtudeHttp.a_(tF.rep.prem); EtudeHttp.a_(tF.rep.entete); } else { tF.rep=new RqtRepHttp(); } } fen.affRqtRep(fen.CLIENT); fen.validate(); } } // fin class RfxEnvoieRequete implements ActionListener // Partie serveur Http ////////////////////// /** Création d'un serveur qui écoute sur le port 'p' */ class MonServeur extends Thread { int portEcoute; ServerSocket ecoute; // EtudeHttp fen; // pour fournir au traitement de réponse // Lance un serveur qui va écouter sur p // MonServeur(int p, EtudeHttp f) throws IOException { MonServeur(int p) throws IOException { // fen=f; portEcoute=p; ecoute = new ServerSocket(portEcoute); start(); } /* Attente des appels clients; sur un appel: ouvrir une socket, répondre au client(objet ReponseHttp) */ public void run() { try { while(true) { Socket socVClient = ecoute.accept(); EtudeHttp.a_("MonServeur: réponse vers:"+ socVClient.getInetAddress()+":"+socVClient.getPort()); // ReponseHttp c = new ReponseHttp(socVClient, fen); ReponseHttp c = new ReponseHttp(socVClient); } } catch(IOException e){EtudeHttp.a("Traitement client",e); } } } // fin class MonServeur extends Thread class MonServeurF extends MonServeur { EtudeHttp fen; // pour fournir au traitement de réponse // Lance un serveur qui va écouter sur p MonServeurF(int p, EtudeHttp f) throws IOException { super(p); fen=f; } /* Attente des appels clients; sur un appel: ouvrir une socket, répondre au client(objet ReponseHttp) */ public void run() { try { while(true) { Socket socVClient = ecoute.accept(); EtudeHttp.a_("MonServeur: réponse vers:"+ socVClient.getInetAddress()+":"+socVClient.getPort()); ReponseHttpF c = new ReponseHttpF(socVClient, fen); } } catch(IOException e){EtudeHttp.a("Traitement client",e); } } } // fin class MonServeurF extends Thread /** Traitement d'une réponse à un client */ class ReponseHttp extends Thread { Socket socSurSeveur; OutputStream versClient; BufferedReader depuisClient; ReponseHttp(Socket cl) { socSurSeveur=cl; try { versClient = socSurSeveur.getOutputStream(); depuisClient = new BufferedReader( new InputStreamReader(socSurSeveur.getInputStream())); } catch(IOException e){EtudeHttp.a("Création flot vers client",e); } this.start(); } /** Récupère la requête et y répond si l'URL est de la forme http://127.0.0.1:8383//machine:80/index.html?a=9 alors le serveur sert de passerelle: il redirige la requête vers machine:80, intercepte la réponse pour affichage, et la renvoie au client. */ public void run() { String msgErr=""; RqtRepHttp rqt=new RqtRepHttp(), rep=new RqtRepHttp(); // Récupérer la requête, y répondre ou la faire suivre (cas passerelle) try { // msgErr = recupRqt(depuisClient,rqt); // on prépare la réponse (corps avant en-tête // afin de pouvoir connnaître Content-length) et on l'envoie creeReponse(rqt,rep); } catch(IOException e){EtudeHttp.a("Réception depuis client",e); } finally { try { socSurSeveur.close(); } catch(IOException e){}; } } // fin run() static String recupRqt(BufferedReader f, RqtRepHttp rqt) throws IOException { String msgErr=""; String ligne; rqt.prem = f.readLine(); // Récupérer l'en-tête rqt.entete=""; ligne = f.readLine(); if(ligne==null) { msgErr="Requête incorrecte"; } else { // on cherche l'en-tête String attLong = "Content-Length: ", attType = "Content-Type: "; int lgCorps = 0; boolean estTexte = false; while (ligne.length() > 0) { // Attribut longueur ou type if (ligne.indexOf(attLong) >= 0) { lgCorps = Integer.parseInt(ligne.substring(attLong.length())); } else if (ligne.indexOf(attType) >= 0) { rqt.typeCorps = ligne.substring(attType.length()); estTexte = ligne.indexOf("text/") >= 0; } rqt.entete += ligne + "\n"; ligne = f.readLine(); } // Récupérer le corps byte corOct[] = new byte[lgCorps]; for (int i = 0; i < lgCorps; i++) corOct[i] = (byte) f.read(); rqt.corps = corOct; } return msgErr; } // fin recupRqt static void creeReponse(RqtRepHttp rqt, RqtRepHttp rep) { rep.prem="HTTP/1.0 200 OK"; rep.typeCorps="text/html"; rep.corps=("<html><head><title>Reponse de Mapomme</title></head>\n" +"<body text='green'>\n" +"<h1>Merci pour votre appel<br> du "+EtudeHttp.date()+"</h1>\n" +"J'ai recu:<hr><pre>"+rqt.prem+"\n"+rqt.entete+"</pre>\n" +"</body></html>\n").getBytes(); rep.entete = "Serveur: Mapomme\n"+"Content-Length:"+rep.corps.length+"\n"; rep.msg=""; } // Partie client Http ///////////////////// /** Envoie d'une requête vers mac sur le port port et renvoie la réponse rep Si envoie échoue rep.msg est non vide */ public static RqtRepHttp envoieRqt(String mac, int port, RqtRepHttp rqt) { RqtRepHttp rep= new RqtRepHttp(); Socket uneSoc=null; int lgCorps=0; boolean estTexte=false; try{ uneSoc = new Socket(mac,port); } catch(IOException e){ rep.msg = "Erreur création socket vers "+mac+':'+port; return rep; } try { // Envoyer la requête, récupérer la réponse rep.msg="Erreur création flots vers/depuis socket"; PrintStream versServeur = new PrintStream(uneSoc.getOutputStream()); versServeur.print(rqt.prem+"\n"+rqt.entete+"\n"+rqt.corps); InputStream depuisServeur = uneSoc.getInputStream(); rep.msg="Problème pendant lecture de l'en-tête"; lgCorps = recupEtatEntete( depuisServeur, rep); estTexte = rep.typeCorps.indexOf("text") >= 0; // Corps jusqu'à la fin rep.msg="Problème pendant lecture du corps"; byte corOct[]= new byte[lgCorps]; for(int i=0; i<lgCorps; i++) corOct[i]= (byte)depuisServeur.read(); rep.corps=corOct; rep.msg=""; } catch(IOException e){} try{ if(uneSoc!=null) uneSoc.close(); } catch(IOException e) { rep.msg="Erreur fermeture socket"; } return rep; } // fin envoieRqt /** Récupère état et entête à partir du flot d'octets f issu du serveur */ static int recupEtatEntete(InputStream f,RqtRepHttp rep) throws IOException { int lgCorps=0; String attLong="Content-Length: ", attType="Content-Type: "; byte b[] = new byte[10000], RC='\n', FL='\r'; int n; String ligne; // récupérer l'état de la réponse n=0; do b[n++]=(byte)f.read(); while(b[n-1] != RC); rep.prem = new String(b, 0, n-2); // En-tête jusqu'à une ligne vide rep.msg = "lecture en-tête"; n=0; do b[n++]=(byte)f.read(); while(b[n-1] != RC); rep.entete = ""; while(b[0] != FL && b[0] != RC) { ligne = new String(b, 0, n-2); // Attribut longueur ou type if (ligne.indexOf(attLong) >= 0) { lgCorps=Integer.parseInt(ligne.substring(attLong.length())); } else if (ligne.indexOf(attType) >= 0) { rep.typeCorps = ligne.substring(attType.length()); } rep.entete += ligne+"\n"; n=0; do b[n++]=(byte) f.read(); while(b[n - 1] != RC); } return lgCorps; } } // fin class ReponseHttp extends Thread /** Traitement d'une réponse à un client */ class ReponseHttpF extends ReponseHttp { EtudeHttp fen; ReponseHttpF(Socket cl, EtudeHttp f) { super(cl); fen=f; try { versClient = socSurSeveur.getOutputStream(); depuisClient = new BufferedReader( new InputStreamReader(socSurSeveur.getInputStream())); } catch(IOException e){EtudeHttp.a("Création flot vers client",e); } // this.start(); } /** Récupère la requête et y répond si l'URL est de la forme http://127.0.0.1:8383//machine:80/index.html?a=9 alors le serveur sert de passerelle: il redirige la requête vers machine:80, intercepte la réponse pour affichage, et la renvoie au client. */ public void run() { String msgErr="", macPortSer="", mac=""; String tChaine[] = new String[] {"","",""}; RqtRepHttp rqt=new RqtRepHttp(), rep=new RqtRepHttp(); int port=0; boolean estPasserelle=false; // passerelle ou simple serveur // Récupérer la requête, y répondre ou la faire suivre (cas passerelle) try { // La commande; y-a-t-il indication d'un serveur ? msgErr = recupRqt(depuisClient,rqt); port = extraitMacPortSer(rqt.prem,tChaine); estPasserelle = (port>0); // si indication, la commande change rqt.prem=tChaine[0]; macPortSer=tChaine[1]; mac=tChaine[2]; EtudeHttp.a_(":"+rqt.prem+", :"+macPortSer+", :"+port); if(estPasserelle) { // On sert de passerelle, donc on envoie cette requête à macPortSer // modifier la commande et l'entête (changer serveur - Host:) rqt.entete=this.modifEntete(rqt.entete,macPortSer); EtudeHttp.a_(":"+rqt.entete+", :"+mac+":"+port); rep = ReponseHttp.envoieRqt(mac,port,rqt); } else { // Pas d'autre serveur: on prépare la réponse (corps avant en-tête creeReponse(rqt,rep); } versClient.write((rep.prem+"\n"+rep.entete+"\n").getBytes()); versClient.write(rep.corps); // flotVersClient.write(rep.corps); versClient.close(); rep.msg=""; } catch(IOException e){EtudeHttp.a("Réception depuis client",e); } finally { try { socSurSeveur.close(); } catch(IOException e){}; } fen.txtFen[fen.SERVEUR].rqt=rqt; fen.txtFen[fen.SERVEUR].rep=rep; fen.txtFen[fen.SERVEUR].qqinfo=msgErr; fen.affRqtRep(fen.SERVEUR + (estPasserelle?1:0)); } // fin run() /** * @param cmd commande avec pseudo-url éventuelle * @param tC[0]=nouvelle commande; tc[1]=machine:port; tc[2]=machine * @return port=0 si pas de pseudo-url<br> * port=80 si machine et pas d'indication de port<br> */ static int extraitMacPortSer(String cmd, String tC[]) { int pesp, port; String h="Host:", macPortSer="", mac=""; port=0; pesp = cmd.indexOf(" ")+1; if(pesp>=0) { macPortSer=cmd.substring(pesp); // EtudeHttp.a_("ressource:"+macPortSer); if(macPortSer.indexOf("//")==0) { // il existe une indication de machine; extraire nom de machine macPortSer = macPortSer.substring(2,macPortSer.indexOf("/",3)); // nouvelle commande String ch = cmd.substring(3+pesp+macPortSer.length()); tC[0] = cmd.substring(0,pesp+1)+ch; // mac = nom de machine : numéro de port mac= macPortSer; int pdp = macPortSer.indexOf(":"); if(pdp >= 0) { port = Integer.parseInt(macPortSer.substring(pdp + 1)); mac = macPortSer.substring(0,pdp); // mac réduit à la machine } else port=80; } else { tC[0]=cmd; macPortSer=""; } } tC[1]=macPortSer; tC[2]=mac; return port; } /** modifier l'entête (changer serveur - Host:) */ static String modifEntete(String entete, String macPort) { String h="Host:", e=""; // entete modifie int pah, prc, pmsp; // position après Host: et de machine:port pah = entete.indexOf(h)+h.length(); prc = entete.indexOf("\n",pah); if(pah<h.length() || prc<0) return entete; // pas de ligne Host: e = entete.substring(0,pah)+' '+macPort+entete.substring(prc); // EtudeHttp.a_("modifEntete:\n"+e); return e; } } // fin class ReponseHttpF extends Thread // fin EtudeHttp.java // fin