Skip to content

Commit b54b895

Browse files
author
Maxime Labelle
committed
New - Added a sample program, to illustrate the usage of the tracking Middleware.
1 parent 91eccde commit b54b895

File tree

8 files changed

+454
-0
lines changed

8 files changed

+454
-0
lines changed

src/WebApi.sln

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 2013
4+
VisualStudioVersion = 12.0.30723.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "WebApi\WebApi.csproj", "{F23152A5-D887-4E25-A91E-5A4DC2176EC4}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpringComp.Owin", "SpringComp.Owin\SpringComp.Owin.csproj", "{A7041BD1-CA1E-43EC-BAFA-3213150C6411}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpringComp.Owin.Interop", "SpringComp.Interop\SpringComp.Owin.Interop.csproj", "{D504F207-998E-41FE-B8F3-3EB6EED39DC0}"
11+
EndProject
12+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{17D3D7E9-029E-4A92-A763-C6F5D4B34731}"
13+
ProjectSection(SolutionItems) = preProject
14+
.nuget\NuGet.Config = .nuget\NuGet.Config
15+
.nuget\NuGet.exe = .nuget\NuGet.exe
16+
.nuget\NuGet.targets = .nuget\NuGet.targets
17+
EndProjectSection
18+
EndProject
19+
Global
20+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
21+
Debug|Any CPU = Debug|Any CPU
22+
Release|Any CPU = Release|Any CPU
23+
EndGlobalSection
24+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
25+
{F23152A5-D887-4E25-A91E-5A4DC2176EC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26+
{F23152A5-D887-4E25-A91E-5A4DC2176EC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
27+
{F23152A5-D887-4E25-A91E-5A4DC2176EC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{F23152A5-D887-4E25-A91E-5A4DC2176EC4}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{A7041BD1-CA1E-43EC-BAFA-3213150C6411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30+
{A7041BD1-CA1E-43EC-BAFA-3213150C6411}.Debug|Any CPU.Build.0 = Debug|Any CPU
31+
{A7041BD1-CA1E-43EC-BAFA-3213150C6411}.Release|Any CPU.ActiveCfg = Release|Any CPU
32+
{A7041BD1-CA1E-43EC-BAFA-3213150C6411}.Release|Any CPU.Build.0 = Release|Any CPU
33+
{D504F207-998E-41FE-B8F3-3EB6EED39DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34+
{D504F207-998E-41FE-B8F3-3EB6EED39DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
35+
{D504F207-998E-41FE-B8F3-3EB6EED39DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
36+
{D504F207-998E-41FE-B8F3-3EB6EED39DC0}.Release|Any CPU.Build.0 = Release|Any CPU
37+
EndGlobalSection
38+
GlobalSection(SolutionProperties) = preSolution
39+
HideSolutionNode = FALSE
40+
EndGlobalSection
41+
EndGlobal

src/WebApi/App.config

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5+
</startup>
6+
<runtime>
7+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
8+
<dependentAssembly>
9+
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
10+
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
11+
</dependentAssembly>
12+
<dependentAssembly>
13+
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
14+
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
15+
</dependentAssembly>
16+
<dependentAssembly>
17+
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
18+
<bindingRedirect oldVersion="0.0.0.0-5.6.2.0" newVersion="5.6.2.0" />
19+
</dependentAssembly>
20+
<dependentAssembly>
21+
<assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
22+
<bindingRedirect oldVersion="0.0.0.0-5.6.2.0" newVersion="5.6.2.0" />
23+
</dependentAssembly>
24+
<dependentAssembly>
25+
<assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
26+
<bindingRedirect oldVersion="0.0.0.0-5.6.2.0" newVersion="5.6.2.0" />
27+
</dependentAssembly>
28+
</assemblyBinding>
29+
</runtime>
30+
</configuration>

src/WebApi/CustomController.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Net;
5+
using System.Net.Http;
6+
using System.Net.Http.Headers;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using System.Web.Http;
10+
11+
namespace WebApi
12+
{
13+
/// <summary>
14+
/// A simple AspNet WebApi Controller for illustration purposes.
15+
/// </summary>
16+
[RoutePrefix("api/custom")]
17+
public sealed class CustomController : ApiController
18+
{
19+
/// <summary>
20+
/// GET http://host:port/api/custom/resources
21+
/// Returns a list of resources.
22+
/// </summary>
23+
/// <returns>A list of strings.</returns>
24+
[HttpGet]
25+
[Route("resources")]
26+
public IHttpActionResult GetAllResources()
27+
{
28+
var collection = new[]
29+
{
30+
"one",
31+
"two",
32+
"three",
33+
};
34+
35+
36+
return Ok(collection);
37+
}
38+
39+
/// <summary>
40+
/// GET http://host:port/api/custom/stream
41+
/// Returns a streamed buffer.
42+
/// </summary>
43+
/// <returns>A streamed buffer.</returns>
44+
[HttpGet]
45+
[Route("stream/{count}")]
46+
public HttpResponseMessage GetStream(int count)
47+
{
48+
Action<Stream, HttpContent, TransportContext> onStreamAvailable = (stream, content, transport) =>
49+
{
50+
using (stream)
51+
{
52+
foreach (var s in GetStrings(count))
53+
{
54+
var buffer = Encoding.UTF8.GetBytes(s);
55+
stream.WriteAsync(buffer, 0, buffer.Length);
56+
}
57+
58+
stream.FlushAsync();
59+
}
60+
};
61+
62+
var response = Request.CreateResponse();
63+
response.Content = new PushStreamContent(onStreamAvailable);
64+
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
65+
66+
return response;
67+
}
68+
69+
private IEnumerable<string> GetStrings(int count)
70+
{
71+
for (var index = 0; index < count; index++)
72+
yield return "Sed ut perspiciatis nulla pariatur?\r\n";
73+
}
74+
75+
76+
[HttpGet]
77+
[Route("resources-async")]
78+
public async Task<IHttpActionResult>GetAllResourcesAsync()
79+
{
80+
var collection = new[]
81+
{
82+
"one",
83+
"two",
84+
"three",
85+
};
86+
87+
var task = Task<IEnumerable<string>>.Factory.StartNew(() => collection);
88+
var c = await task;
89+
return Ok(c);
90+
}
91+
92+
/// <summary>
93+
/// POST http://host:port/api/custom/post
94+
/// Reads the incoming HTTP Request stream.
95+
/// </summary>
96+
/// <returns></returns>
97+
[HttpPost]
98+
[Route("post-async")]
99+
public async Task<IHttpActionResult> PostStreamAsync()
100+
{
101+
// consume the stream, to simulate processing
102+
using (var stream = await Request.Content.ReadAsStreamAsync())
103+
{
104+
var count = 0;
105+
var buffer = new byte[4096];
106+
while ((count = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
107+
/* do nothing */;
108+
}
109+
110+
return Ok();
111+
}
112+
}
113+
}

src/WebApi/HttpTrackingStore.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using Newtonsoft.Json;
6+
using SpringComp.Owin.Interop;
7+
8+
namespace App
9+
{
10+
/// <summary>
11+
/// Dummy implementation of the <see cref="HttpEntry"/> interface to file, for illustration purposes.
12+
/// </summary>
13+
public sealed class HttpTrackingStore : IHttpTrackingStore
14+
{
15+
private readonly string path_ = Path.GetTempPath();
16+
17+
public async System.Threading.Tasks.Task InsertRecordAsync(HttpEntry record)
18+
{
19+
var path = Path.Combine(path_, record.TrackingId.ToString("d"));
20+
using (var stream = File.OpenWrite(path))
21+
using (var writer = new StreamWriter(stream))
22+
await writer.WriteAsync(JsonConvert.SerializeObject(record));
23+
24+
Console.WriteLine("Verb: {0}", record.Verb);
25+
Console.WriteLine("RequestUri: {0}", record.RequestUri);
26+
Console.WriteLine("Request: {0}", record.Request);
27+
Console.WriteLine("RequestLength: {0}", record.RequestLength);
28+
29+
Console.WriteLine("StatusCode: {0}", record.StatusCode);
30+
Console.WriteLine("ReasonPhrase: {0}", record.ReasonPhrase);
31+
Console.WriteLine("Response: {0}", record.Response);
32+
Console.WriteLine("Content-Length: {0}", record.ResponseLength);
33+
34+
Console.WriteLine("FILE {0} saved.", path);
35+
}
36+
}
37+
}

src/WebApi/Program.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Owin;
3+
using SpringComp.Owin;
4+
5+
namespace App
6+
{
7+
using System;
8+
using System.Web.Http;
9+
using Microsoft.Owin.Hosting;
10+
using Owin;
11+
12+
class Program
13+
{
14+
static void Main(string[] args)
15+
{
16+
const string address = "http://localhost:12345";
17+
18+
using (WebApp.Start<Startup>(address))
19+
{
20+
Console.WriteLine("Listening requests on {0}.", address);
21+
Console.WriteLine("Please, press ENTER to shutdown.");
22+
Console.ReadLine();
23+
}
24+
}
25+
}
26+
27+
public sealed class OpaqueMiddleware : OwinMiddleware
28+
{
29+
public OpaqueMiddleware(OwinMiddleware next)
30+
: base(next)
31+
{
32+
}
33+
34+
public override async Task Invoke(IOwinContext context)
35+
{
36+
await Next.Invoke(context);
37+
}
38+
}
39+
40+
public sealed class Startup
41+
{
42+
private readonly HttpConfiguration configuration_ = new HttpConfiguration();
43+
44+
public void Configuration(IAppBuilder application)
45+
{
46+
// Microsoft Azure table columns can hold values less than or equal to 64KB.
47+
48+
application.UseHttpTracking(
49+
new HttpTrackingOptions
50+
{
51+
TrackingStore = new HttpTrackingStore(),
52+
TrackingIdPropertyName = "x-tracking-id",
53+
MaximumRecordedRequestLength = 64 * 1024,
54+
MaximumRecordedResponseLength = 64 * 1024,
55+
}
56+
);
57+
58+
application.UseWebApi(configuration_);
59+
60+
// automatically registers routes for the
61+
// AspNet WebApi Controllers available in this assembly
62+
63+
configuration_.MapHttpAttributeRoutes();
64+
}
65+
}
66+
}

src/WebApi/Properties/AssemblyInfo.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("WebApi")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("WebApi")]
13+
[assembly: AssemblyCopyright("Copyright © 2014")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("2357c55d-6ab1-4e2c-bfd6-fee5db9006c6")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

0 commit comments

Comments
 (0)