jueves, 10 de junio de 2010

Un servidor web con WCF.

Pues les cuento, este es mi primer pos luego de ser ingeniero en ciencias informática, el jueves pasado presenté el trabajo de diploma el cual obtuvo una gran aceptación. Pues adentrándonos en el tema del pos, el cual trae como objetivo la realización de un servidor web con WCF. Este servidor es bien simple de implementar gracias a las bondades de WCF.Este servidor se resume en 3 clases fundamentales.
  1. La interfaces o contrato que define el servicio que expondrá nuestro servidor para que sea consumido por los navegadores web.
  2. La implementación de esta interfaz que sería el plato fuerte del servidor (incluso integración simple con php).
  3. El código principal en el cual se define el server de WCF y todas las configuraciones para utilizarlo.
La interfaz:


using System.IO;using System.ServiceModel;
using System.ServiceModel.Web;

namespace WEBServer
{
    [ServiceContract]
    public interface IFileHost
    {
        [OperationContract, WebGet(UriTemplate = "/{*filename}")]
        Stream Files(string filename);
    }
}

La implementación:

Esta cuenta con un método principal Files, este retorna el Stream relacionada al fichero solicitado por el navegador web. Tiene en cuenta 3 variantes fundamentales, en el casa de solicitar una carpeta, revisa dentro de la carpeta un grupo de ficheros por defecto y los retorna, en esto caso son index.php, index.html y defaul.php. La próxima variante es en el caso de solicitar un archivo, aquí comprobamos si tiene como extención .php, de tenerlo se realiza una llamada al interprete de PHP para que genere el código html correspondiente a este fichero.

private Stream PhpFileToHtml(string filePath)
        {
            var p = new Process
                        {
                            StartInfo =
                                {
                                    FileName = "php\\php.exe",
                                    Arguments = filePath,
                                    RedirectStandardOutput = true,
                                    UseShellExecute = false
                                },
                        };

            p.Start();
            return p.StandardOutput.BaseStream;
        }


De no ser php el fichero lo retornamos directamente, que sería tan sencillo cómo:


return new FileStream(filePath, FileMode.Open, FileAccess.Read);


Para que el navegador entienda correctamente los Stream que se retornan es necesario incluir en la cabecera HTTP el mime type correspondiente a cada tipo de fichero, para esto hago uso de la función  MimeType, esta dado una extención retorna el mime adecuado.

Aquí tiene el código completo de esta clase.



using System.Collections.Generic;
using System.IO;
using System.ServiceModel.Web;
using System.Net;
using System.Diagnostics;


namespace WEBServer
{
    public class Service : IFileHost
    {

        public Stream Files(string filename)
        {
            var filePath = "Hosting/" + filename;
            
            if (Directory.Exists(filePath))
            {
                filePath += filename.EndsWith("/") ? "" : "/";
                foreach (var file in DefaultFiles())
                {
                    var tempFile = filePath + "/" + file;
                    if (File.Exists(tempFile))
                    {
                        return FileToHtml(tempFile);
                    }
                }
            }
            else if (File.Exists(filePath))
            {
                return FileToHtml(filePath);
            }
            else
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
                return new MemoryStream();
            }
            return null;
        }

        private Stream FileToHtml(string filePath)
        {
            int extIndex = filePath.LastIndexOf(".");
            string extension = filePath.Substring(extIndex, filePath.Length - extIndex);
            WebOperationContext.Current.OutgoingResponse.ContentType = MimeType(extension);

            switch (extension.ToLower())
            {
                case ".php":
                    return PhpFileToHtml(filePath);
                default:
                    return new FileStream(filePath, FileMode.Open, FileAccess.Read);
            }
        }

        private Stream PhpFileToHtml(string filePath)
        {
            var p = new Process
                        {
                            StartInfo =
                                {
                                    FileName = "php\\php.exe",
                                    Arguments = filePath,
                                    RedirectStandardOutput = true,
                                    UseShellExecute = false
                                },
                        };

            p.Start();
            return p.StandardOutput.BaseStream;
        }

        private string MimeType (string extension)
        {
            switch (extension)
            {
                case ".ai": return "application/postscript";
                case ".aif": return "audio/x";
                case ".aifc": return "audio/x";
                case ".aiff": return "audio/x";
                case ".asc": return "text/plain";
                case ".au": return "audio/basic";
                case ".avi": return "video/x";
                case ".bcpio": return "application/x";
                case ".bin": return "application/octet";
                case ".c": return "text/plain";
                case ".cc": return "text/plain";
                case ".ccad": return "application/clariscad";
                case ".cdf": return "application/x";
                case ".class": return "application/octet";
                case ".cpio": return "application/x";
                case ".cpt": return "application/mac";
                case ".csh": return "application/x";
                case ".css": return "text/css";
                case ".dcr": return "application/x";
                case ".dir": return "application/x";
                case ".dms": return "application/octet";
                case ".doc": return "application/msword";
                case ".drw": return "application/drafting";
                case ".dvi": return "application/x";
                case ".dwg": return "application/acad";
                case ".dxf": return "application/dxf";
                case ".dxr": return "application/x";
                case ".eps": return "application/postscript";
                case ".etx": return "text/x";
                case ".exe": return "application/octet";
                case ".ez": return "application/andrew";
                case ".f": return "text/plain";
                case ".f90": return "text/plain";
                case ".fli": return "video/x";
                case ".gif": return "image/gif";
                case ".gtar": return "application/x";
                case ".gz": return "application/x";
                case ".h": return "text/plain";
                case ".hdf": return "application/x";
                case ".hh": return "text/plain";
                case ".hqx": return "application/mac";
                case ".htm": return "text/html";
                case ".html": return "text/html";
                case ".php": return "text/html";
                case ".ice": return "x";
                case ".ief": return "image/ief";
                case ".iges": return "model/iges";
                case ".igs": return "model/iges";
                case ".ips": return "application/x";
                case ".ipx": return "application/x";
                case ".jpe": return "image/jpeg";
                case ".jpeg": return "image/jpeg";
                case ".jpg": return "image/jpeg";
                case ".js": return "application/x";
                case ".kar": return "audio/midi";
                case ".latex": return "application/x";
                case ".lha": return "application/octet";
                case ".lsp": return "application/x";
                case ".lzh": return "application/octet";
                case ".m": return "text/plain";
                case ".man": return "application/x";
                case ".me": return "application/x";
                case ".mesh": return "model/mesh";
                case ".mid": return "audio/midi";
                case ".midi": return "audio/midi";
                case ".mif": return "application/vnd.mif";
                case ".mime": return "www/mime";
                case ".mov": return "video/quicktime";
                case ".movie": return "video/x";
                case ".mp2": return "audio/mpeg";
                case ".mp3": return "audio/mpeg";
                case ".mpe": return "video/mpeg";
                case ".mpeg": return "video/mpeg";
                case ".mpg": return "video/mpeg";
                case ".mpga": return "audio/mpeg";
                case ".ms": return "application/x";
                case ".msh": return "model/mesh";
                case ".nc": return "application/x";
                case ".oda": return "application/oda";
                case ".pbm": return "image/x";
                case ".pdb": return "chemical/x";
                case ".pdf": return "application/pdf";
                case ".pgm": return "image/x";
                case ".pgn": return "application/x";
                case ".png": return "image/png";
                case ".pnm": return "image/x";
                case ".pot": return "application/mspowerpoint";
                case ".ppm": return "image/x";
                case ".pps": return "application/mspowerpoint";
                case ".ppt": return "application/mspowerpoint";
                case ".ppz": return "application/mspowerpoint";
                case ".pre": return "application/x";
                case ".prt": return "application/pro_eng";
                case ".ps": return "application/postscript";
                case ".qt": return "video/quicktime";
                case ".ra": return "audio/x";
                case ".ram": return "audio/x";
                case ".ras": return "image/cmu";
                case ".rgb": return "image/x";
                case ".rm": return "audio/x";
                case ".roff": return "application/x";
                case ".rpm": return "audio/x";
                case ".rtf": return "text/rtf";
                case ".rtx": return "text/richtext";
                case ".scm": return "application/x";
                case ".set": return "application/set";
                case ".sgm": return "text/sgml";
                case ".sgml": return "text/sgml";
                case ".sh": return "application/x";
                case ".shar": return "application/x";
                case ".silo": return "model/mesh";
                case ".sit": return "application/x";
                case ".skd": return "application/x";
                case ".skm": return "application/x";
                case ".skp": return "application/x";
                case ".skt": return "application/x";
                case ".smi": return "application/smil";
                case ".smil": return "application/smil";
                case ".snd": return "audio/basic";
                case ".sol": return "application/solids";
                case ".spl": return "application/x";
                case ".src": return "application/x";
                case ".step": return "application/STEP";
                case ".stl": return "application/SLA";
                case ".stp": return "application/STEP";
                case ".sv4cpio": return "application/x";
                case ".sv4crc": return "application/x";
                case ".swf": return "application/x";
                case ".t": return "application/x";
                case ".tar": return "application/x";
                case ".tcl": return "application/x";
                case ".tex": return "application/x";
                case ".texi": return "application/x";
                case ".texinfo": return "application/x";
                case ".tif": return "image/tiff";
                case ".tiff": return "image/tiff";
                case ".tr": return "application/x";
                case ".tsi": return "audio/TSP";
                case ".tsp": return "application/dsptype";
                case ".tsv": return "text/tab";
                case ".txt": return "text/plain";
                case ".unv": return "application/i";
                case ".ustar": return "application/x";
                case ".vcd": return "application/x";
                case ".vda": return "application/vda";
                case ".viv": return "video/vnd.vivo";
                case ".vivo": return "video/vnd.vivo";
                case ".vrml": return "model/vrml";
                case ".wav": return "audio/x";
                case ".wrl": return "model/vrml";
                case ".xbm": return "image/x";
                case ".xlc": return "application/vnd.ms";
                case ".xll": return "application/vnd.ms";
                case ".xlm": return "application/vnd.ms";
                case ".xls": return "application/vnd.ms";
                case ".xlw": return "application/vnd.ms";
                case ".xml": return "text/xml";
                case ".xpm": return "image/x";
                case ".xwd": return "image/x";
                case ".xyz": return "chemical/x";
                case ".zip": return "application/zip";
                default :
                    return "application/octet-stream";
            }
        }

        private List DefaultFiles()

        {

            return new List

                       {

                           "index.php",

                           "index.html",

                           "defaul.php",

                       };

        }

    }

}


Para culminar solo nos falta crear el servidor y hostiarlo, el codigo que permite hacer esto es el siguiente.

string baseAddress = "http://" + Environment.MachineName + ":80/";
var host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IFileHost), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Server is ready.");
Console.Write("Press ENTER to close the server");
Console.ReadLine();
host.Close();

Listo ya tenemos nuestro servidor http listo para ser usado y para ser modificado a su antojo agregándole todo lo que se les ocurra.

¿Donde se colocan los sitios para que sean hosteados?
Dentro de la carpeta que se encuentra en la raíz del programa que tiene por nombre Hosting.
¿Por qué no funcionan las paginas php?
 Esto se debe a que debemos cambiar la dirección del interprete PHP para que pueda ser ejecutado.

StartInfo =
  {
    //Coloca aquí la dirección de donde se encuentre el PHP en la pc.
    FileName = "php\\php.exe",                                  
    Arguments = filePath,
    RedirectStandardOutput = true,
    UseShellExecute = false
   } 
Descarga el proyecto completo desde aquí.

No hay comentarios:

Publicar un comentario