紺Azure ポート80でのアプリケーションのデバッグ

Windows Azureプラットフォームでアプリケーションを開発するとき、異なるポートでデバッグアセンブリを実行する特性に我慢する必要がありました。 しかし、クロスドメインAJAXを積極的にデバッグし始めたとき、この問題は特に深刻になりました。 スクリプトでは、jsスクリプトのテキストで絶対URLを使用する必要があったためです。 URLにポート番号を記述する必要がありました:http://127.0.0.1:81/bla-bla-bla。 アプリケーションを再起動したときにポートが変更された場合、アセンブリがポート81で開始されるようにdevfabricを再起動する必要がありました。 再起動には貴重な時間がかかり、イライラが増加しました。
ある時点で忍耐が尽きたため、1つのポートでアプリケーションをデバッグするためのツールを作成することにしました。 要求を受信し、実行中のAzureインスタンスにリダイレクトするASPXアプリケーションです。 これにより、Azureが現在実行されているポートを心配する必要がなくなります。

プリセット


開発プロセス中に、 Azureproxy.comでAzureインスタンスが利用できるように、リバースプロキシのようなものを作成するというアイデアが生まれました。 これを行うには、マシン上でまだ実行されているIIS 7.5を使用します。
IISマネージャーで、AzureProxyアプリケーションプールを追加します
アプリケーションプールの追加
.Net Frameworkの4番目のバージョンを示します。
そして、ウェブサイトを追加します
サイトを追加する
ここでは、サイトの名前「AzureProxy」、アプリケーションプール「AzureProxy」、物理パス-任意(ここではD:\ AzureProxy \)を指定する必要があります。 バインディングも指定する必要があります:IPアドレス-127.0.0.1 、ポート-80、ホスト名-azureproxy.com
IIS用のUrl Rewriteモジュールも必要です。 まだインストールしていない場合は、 www.iis.net / download / URLRewriteにアクセスしてインストールする必要があります。
次のステップは、azureproxy.comをhostsファイルに追加することです。
エディターでファイルC:\ Windows \ System32 \ drivers \ etc \ hostsを開き、それに行を追加します
127.0.0.1 azureproxy.com
準備段階が完了しました。

プログラム可能


Visual Studio 2010を開きます。
新しいプロジェクトを作成する
新しいプロジェクトを作成する
プロジェクトタイプ-ASP .NET空のWebアプリケーション。残りはオプションです。
Web.Configファイルを編集します
<? xml version ="1.0" ? >
< configuration >
< system.web >
< compilation debug ="true" targetFramework ="4.0" />
< pages enableViewStateMac ="false" />
</ system.web >
< system.webServer >
< modules runAllManagedModulesForAllRequests ="true" >
< add name ="AzureProxyModule" type ="AzureProxy.AzureProxyModule, AzureProxy" />
</ modules >
< rewrite >
< rules >
< rule name ="All" stopProcessing ="true" >
< match url ="^(.*)$" />
< action type ="Rewrite" url ="/Default.aspx?url={HtmlEncode:{R:0}}" />
</ rule >
</ rules >
</ rewrite >
</ system.webServer >
</ configuration >

* This source code was highlighted with Source Code Highlighter .


新しいWebフォームを追加する
新しいウェブフォーム
Default.aspxという名前
そして、私たちはそこにだけ残し
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AzureProxy.Default" %>


次に、新しいクラスを追加します。
新しいクラス
次のようなAzureProxyModule.csという名前

using System;
using System.Net;
using System.IO;
using System.Configuration;
using System.Collections. Generic ;
using System.Linq;
using System.Web;
using System.Threading;

namespace AzureProxy
{
public class AzureProxyModule : IHttpModule
{

const string Domain = "127.0.0.1" ;
const int MaxPort = 110;

public static string Port = "" ;
public Queue< int > ports = new Queue< int >();
public List <Thread> threads = new List <Thread>();
public bool ThreadsLive = false ;

public AzureProxyModule()
{
}

public String ModuleName
{
get { return "AzureProxyModule" ; }
}

public void Init(HttpApplication httpApp)
{

httpApp.BeginRequest +=
new EventHandler( this .OnBeginRequest);

httpApp.EndRequest +=
new EventHandler( this .OnEndRequest);
}

public void OnBeginRequest( object o, EventArgs ea)
{
}

public void OnEndRequest( object o, EventArgs ea)
{
HttpApplication httpApp = (HttpApplication)o;
if (Port.Length == 0)
{
SearchPort();
}

DoRequest();

}

public void DoRequest()
{

byte [] buffer = new byte [4096];
HttpContext ctx;
ctx = HttpContext .Current;
if (ctx.Request.QueryString[ "url" ] == null ) return ;

HttpWebRequest myHttp = (HttpWebRequest)HttpWebRequest.Create( "http://" + Domain + ":" + Port + ctx.Request.RawUrl.ToString());
myHttp.AllowAutoRedirect = false ;
myHttp.KeepAlive = true ;
myHttp.CookieContainer = new CookieContainer();
myHttp.UserAgent = ctx.Request.UserAgent;
foreach ( string CookieName in ctx.Request.Cookies.AllKeys)
{
if (ctx.Request.Cookies[CookieName].Domain != null )
{
myHttp.CookieContainer.Add( new Cookie(ctx.Request.Cookies[CookieName].Name, ctx.Request.Cookies[CookieName].Value, ctx.Request.Cookies[CookieName].Path, ctx.Request.Cookies[CookieName].Domain));
}
else
{
myHttp.CookieContainer.Add( new Cookie(ctx.Request.Cookies[CookieName].Name, ctx.Request.Cookies[CookieName].Value, ctx.Request.Cookies[CookieName].Path, Domain));
}
}
myHttp.ContentType = ctx.Request.ContentType;

if (ctx.Request.HttpMethod == "POST" )
{
myHttp.Method = "POST" ;
myHttp.AllowWriteStreamBuffering = true ;
myHttp.ContentLength = ctx.Request.InputStream.Length;
Stream requestStream = myHttp.GetRequestStream();
int length = 0;
while ((length = ctx.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
{
requestStream.Write(buffer, 0, length);
}
}

try
{
WebResponse response = myHttp.GetResponse();

if (response.Headers[ "Location" ] != null )
{
ctx.Response.Redirect(response.Headers[ "Location" ]);
}

using ( Stream stream = response.GetResponseStream())
{
using (MemoryStream memoryStream = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, count);

} while (count != 0);

ctx.Response.ContentType = response.ContentType;
foreach ( string HeaderKey in response.Headers.Keys)
{
ctx.Response.AddHeader(HeaderKey, response.Headers[HeaderKey]);
}

ctx.Response.BinaryWrite(memoryStream.ToArray());

}
}
}
catch (WebException code)
{
switch (code.Message)
{
case "Unable to connect to the remote server" :
SearchPort();
DoRequest();
break ;
case "The remote server returned an error: (404) Not Found." :
ctx.Response.Status = "404 File Not Found" ;
break ;
}
return ;
}
}

public void SearchPort()
{
Port = "" ;
for ( int port = 81; port < MaxPort; port++)
{
ports.Enqueue(port);
threads.Add( new Thread( new ThreadStart(PortTest)));
}
threads.ForEach( new Action<Thread>(ThreadStart));

while (TreadsIsLive() && (Port.Length == 0))
{
//
}

//
threads.ForEach( new Action<Thread>(ThreadAbort));
}

public void Dispose() { }

public bool TreadsIsLive()
{
ThreadsLive = false ;
threads.ForEach( new Action<Thread>(ThreadTest));
return true ;
}

public void ThreadTest(Thread t)
{
ThreadsLive = ThreadsLive || t.IsAlive;
}

protected void ThreadStart(Thread t)
{
try
{
ThreadsLive = true ;
if (!t.IsAlive) t.Start();
}
catch { }
}

protected void ThreadAbort(Thread t)
{
t.Abort();
}

protected void PortTest()
{
int port;
try
{
port = ports.Dequeue();

HttpWebRequest myHttpWebRequest =
(HttpWebRequest)HttpWebRequest.Create( "http://" + Domain + ":" + port.ToString());
try
{
HttpWebResponse myHttpWebResponse =
(HttpWebResponse)myHttpWebRequest.GetResponse();
Port = port.ToString();
return ;
}
catch { }
}
catch { }
}
}
}

* This source code was highlighted with Source Code Highlighter .


アプリケーションをビルドし、IISで公開します
転記

Azureがazureproxy.comで利用可能になりました。

おわりに


使用される手法により、単一のアドレスから実行中のAzureインスタンスへのリクエストをプロキシできます。 子取引で利用可能なポートが並行して検索されるため、ポートをすばやく見つけることができます。 GETリクエストとPOSTリクエストの両方がプロキシされ、着信ストリームがAzureインスタンスに完全に転送されるため、ファイルをアップロードできます。

PSこの記事では、AzureProxyの作成に関する短いチュートリアルを提供します。 必要に応じて、アプリケーションの作成プロセスで発生した問題領域をより詳細に強調できます。

Source: https://habr.com/ru/post/J111100/


All Articles