ServiceStack Razor View wraps content with extra data - servicestack

I'm using ServiceStack with the Razor plugin and returning response objects from my service methods. If the service uses a default view then the response is fine, but if I specify a View in the service method then the http response includes additional data surrounding the content.
Here's a test service class:
[DefaultView("TestView")]
public class TestService : RestServiceBase<Req>
{
public override object OnGet(Req request)
{
var response = new Req { Data = "Hello" };
if (string.IsNullOrEmpty(request.Data))
{
return response;
}
return new HttpResult(response) { View = "TestView" };
}
}
An example raw response including the additional content data looks like this:
HTTP/1.1 200 OK
Server: nginx/1.2.3
Date: Thu, 03 Jan 2013 12:46:33 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: ServiceStack/3.928 Unix/Mono
X-AspNet-Version: 4.0.30319
Cache-Control: private
Set-Cookie: ss-id=KvFQKAyOkkKMajEFeaLiKQ==; path=/
Set-Cookie: ss-pid=nrv3gwEL6EuRE9B8VpAWZA==; path=/; expires=Mon, 03 Jan 2033 12:43:57 GMT
b1
a4
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test page</title>
</head>
<body>
<h1>Test page</h1>
<p>Hello</p>
</body>
</html>
0
0
They look like content length values and end markers. I guess I have something mis-configured, but don't know what. Any ideas?

Related

Does the "Sign In with Google" button require CSP style-src 'unsafe-inline'?

I added a "Sign In with Google" button to my test web app.
I tried to add a CSP following the advise at Setup instructions > Content Security Policy:
script-src https://accounts.google.com/gsi/client;frame-src https://accounts.google.com/gsi/;connect-src https://accounts.google.com/gsi/;style-src https://accounts.google.com/gsi/style;report-uri https://localhost.rubenlaguna.com/csp-report;default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src-attr 'none';upgrade-insecure-requests
The button displays ok, but I see a CSP violation for style-src-elem reported:
csp-report {
'csp-report': {
'document-uri': 'https://localhost.rubenlaguna.com/',
referrer: '',
'violated-directive': 'style-src-elem',
'effective-directive': 'style-src-elem',
'original-policy': "script-src https://accounts.google.com/gsi/client;frame-src https://accounts.google.com/gsi/;connect-src https://accounts.google.com/gsi/;style-src https://accounts.google.com/gsi/style;report-uri https://localhost.rubenlaguna.com/csp-report;default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src-attr 'none';upgrade-insecure-requests",
disposition: 'enforce',
'blocked-uri': 'inline',
'line-number': 383,
'column-number': 8676,
'source-file': 'https://accounts.google.com/gsi/client',
'status-code': 200,
'script-sample': ''
}
}
I can get rid of the violation by adding 'unsafe-inline' to the style-src. But I was wondering if it actually required or not, or if there is a way to get rid of this violation by changing the CSP?
It's possible to avoid the unsafe-inline completely by using nonce (See CSP nonce, style-src nonce)
The CSP violation happens because the google client library (https://accounts.google.com/gsi/client) creates some inline styles. Fortunately, the client library will "pass-through" the document.currentScript.nonce to the inline style. If the inline style has a nonce then you can suppress the CSP violation by allowing 'nonce-xxxx'
First, you need to pass a nonce value to the google client library like this
<script nonce="xxx123" src="https://accounts.google.com/gsi/client" async defer></script>
the nonce should be random value that changes in every reload (see examples below on how to achieve this with express.js)
Then, you add the following in your CSP
style-src https://accounts.google.com/gsi/ 'nonce-xxx123';
If you are using express.js to generate your pages you could have a middleware like this to generate the nonce, store it in the request and set the Content-Security-Policy header:
app.use((req, res, next) => { // express middleware
req.nonce = crypto.randomBytes(16).toString("base64url"); // we'll use when rendering the HTML
const csp = [
`script-src https://accounts.google.com/gsi/client;`,
`frame-src https://accounts.google.com/gsi/;`,
`connect-src https://accounts.google.com/gsi/;`,
`style-src https://accounts.google.com/gsi/style 'nonce-${req.nonce}';`, // NOTE: allow the nonce
`report-uri ${process.env.SITE_ADDRESS}/csp-report;`,
"default-src 'self';",
"base-uri 'self';",
"font-src 'self' https: data:;",
"form-action 'self';",
"frame-ancestors 'self';",
"img-src 'self' data:;",
"object-src 'none';",
"script-src-attr 'none';",
"upgrade-insecure-requests",
];
const csp1 = csp.join("");
res.header("Content-Security-Policy", csp1);
next();
});
Then the req.nonce can be used to render the page (using EJS templates):
app.get("/", (req, res, next) => {
res.render("login", {
google_client_id: process.env.GOOGLE_CLIENT_ID,
site_address: process.env.SITE_ADDRESS,
nonce: req.nonce, //NOTE: the EJS template needs this value
});
});
that will render the template at views/index.ejs using <script nonce="<%=nonce%>" ...:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>HTML 5 Boilerplate</title>
<script nonce="<%=nonce%>" src="https://accounts.google.com/gsi/client" async defer></script>
</head>
<body>
<div>
<div
id="g_id_onload"
data-client_id="<%=google_client_id%>"
data-context="signin"
data-ux_mode="redirect"
data-login_uri="<%=site_address%>/sign-in-with-google-callback"
data-itp_support="true"
></div>
<div
class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left"
></div>
</div>
</body>
</html>

PHPmailer and boundary headers

Is it possible to add/update boundary headers via PHPmailer for the code
$mail->addStringAttachment($test, 'test.txt', 'quoted-printable');
I need to add/update
--b1_KyZbvbrSl55hdWoQf7uUOwdfF2oGjqnCyP6rqNmlA
Content-Type: text/plain; name="test.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=test.txt
to looks like
--b1_KyZbvbrSl55hdWoQf7uUOwdfF2oGjqnCyP6rqNmlA
Content-Type: text/plain; name="test.txt"; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=test.txt
Content-ID: 20cca107-2625-49ce-9357-95254a59147f#127.0.0.1
so for the Content-Type header was added charset parameter and then added new header Content-ID
Any tips on that?
After further investigation it came up that
The addStringEmbeddedImage method lets you set a cid for the
attachment which will set that header for you. You can ignore the
"image" in the method name - it doesn't care what type of content you
attach really.
So in my case it will be
$mail->addStringEmbeddedImage(file_get_contents($file_name, FILE_USE_INCLUDE_PATH), $uuid, $file_name, 'base64', '', 'attachment');
Regarding adding charset parameter to the Content-Type boundary header
quoted-printable transfer encoding is ASCII 7bit safe, so the default
will work fine and it doesn't need an extra charset clause.
For transfer-encoding and charset
$mail->Encoding = 'quoted-printable';
$mail->CharSet = 'UTF-8';
For content-id check addEmbeddedImage method or try adding directly the header like this:
$mail->addCustomHeader('Content-ID', '20cca107-2625-49ce-9357-95254a59147f#127.0.0.1');

trying to reply to an existing email with gmail API

I'm trying to reply to an existing email with Gmail API:
Since I don't have in the existing mail that i want to reply to the headers of References, In-Reply-To then i'm using the Message-ID instead to fill what I'm sending
DB5PR03MB1206D3A24F124BDF43A5C6E683D60#DB5PR03MB1206.eurprd03.prod.outlook.com is the Message-ID header of existing mail.
I've created the following RFC-802:
Content-Type: text/plain; charset="UTF-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
References: <DB5PR03MB1206D3A24F124BDF43A5C6E683D60#DB5PR03MB1206.eurprd03.prod.outlook.com>
In-Reply-To: <DB5PR03MB1206D3A24F124BDF43A5C6E683D60#DB5PR03MB1206.eurprd03.prod.outlook.com>
Subject: sdfasdf
to: "xxx#gmail.com" <aaa#gmail.com>,<xxxx#xxx.me>
from: aaa#gmail.com
aaaaaaaaa
then i get an error:
that an error occured the message wasn't sent.
I read this post but this post presumes that always i have the following two headers:
References
In-Reply-To
Remove References and set In-Reply-To : Message-ID
Content-Type: text/plain; charset="UTF-8" <br />
MIME-Version: 1.0<br />
Content-Transfer-Encoding: 7bit<br />
In-Reply-To: Message-ID<br />
Subject: sdfasdf<br />
to: "xxx#gmail.com" <aaa#gmail.com>,<xxxx#xxx.me><br />
from: aaa#gmail.com<br />
aaaaaaaaa

ServiceStack Ignores Accept Header

Any reason why ServiceStack would ignore the Accept header? The service is hosted in a ASP.NET app and running in debug within the IDE. The first 40 or so calls to the service, using a System.Web.WebRequest object causes the service to respond correctly. After approximately 50 calls a 404 error is detected by the client (breakpoint not hit in the service). From that point forward, the Accept header is ignored. All subsequent requests always return XML.
The client being used...
var client = (HttpWebRequest)WebRequest.Create(uri);
client.Method = WebRequestMethods.Http.Post;
client.AllowWriteStreamBuffering = false;
client.SendChunked = true;
client.ContentType = "multipart/form-data;";
client.Timeout = int.MaxValue; // HACK:REMOVE
client.Accept = "application/json";
The call is a bit messy right now (trying to debug the failure)...
using (FileStream fileStream = File.OpenRead(filePaths[i]))
{
fileStream.Copy(client.GetRequestStream());
}
var responseString = string.Empty;
try { responseString = new StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (String.IsNullOrWhiteSpace(responseString)) { continue; }
PutFileResponse response = null;
try { response = responseString.FromJson<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
try { response = responseString.FromXml<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
continue;
}
}
I left this as-is to show the the response. The first 50 (approx) calls return JSON as requested. After the 404 all subsequent calls always return XML.
Any thoughts?
Edit (2014-02-25 10:35 EST):
After looking at Fiddler this is a bit more odd than I had thought. Of 559 requests, 34 of them result in 404 errors. However the service continues to respond both before and after the error without issue. The 404 error is the first puzzling part. The second item (the switch between XML and JSON is a bit less puzzling but strange nonethless.
The app is a file storage app and is recursing a test directory to push files to the service. Some of the files it is encountering are actual XML files. All files are sent in a Stream, nested in a DTO, with the client adding an Accept header for "application/json" for each request. If an XML file is sent, even though the Accept header has been sent, the service responds with XML.
Example Request Header (session 94):
POST
http://localhost:50205/Files/Put/8178F94DBDBC4AB18F42118AFD01D1A2/AA10C004D624DA892171F8A7E8CD8D05/201760/ServiceStack.xml HTTP/1.1
Content-Type: multipart/form-data;
Accept: application/json
Host: localhost:50205
Transfer-Encoding: chunked
Expect: 100-continue
1000
<?xml version="1.0"?>
<doc>
[SNIP]
</doc>
0
Example Response Header (session #94):
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/xml
Server: Microsoft-IIS/8.0
X-Powered-By: ServiceStack/4.011 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcX1NvdXJjZVxGSUwwMVx0cnVua1xTcG90bGVzc1xGcmFtZXdvcmtzXEZpbGVNYW5hZ2VtZW50XFByb2plY3RzXEZNRi5TdG9yYWdlU2VydmVyLkhvc3RpbmcuUHVibGljXEZpbGVzXFB1dFw4MTc4Rjk0REJEQkM0QUIxOEY0MjExOEFGRDAxRDFBMlxBQTEwQzAwNEQ2MjREQTg5MjE3MUY4QTdFOENEOEQwNVwyMDE3NjBcU2VydmljZVN0YWNrLnhtbA==?=
X-Powered-By: ASP.NET
Date: Tue, 25 Feb 2014 15:19:06 GMT
Content-Length: 563
<?xml version="1.0" encoding="utf-8"?><PutFileResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FMF.StorageServer.Services.Messages.Files"><ResponseStatus xmlns:d2p1="http://schemas.servicestack.net/types" i:nil="true" /><Status><FileSignature><Checksum>AA10C004D624DA892171F8A7E8CD8D05</Checksum><SizeBytes>201760</SizeBytes></FileSignature><IsAvailable i:nil="true" /><IsKnown i:nil="true" /><IsOnDisk i:nil="true" /><IsSuccessful i:nil="true" /><StatusMessage i:nil="true" /></Status></PutFileResponse>
The unfortunate part of this is that I would have to detect the inner structure of every file before sending it to the server and could never trust the file extension. Either that or always assume that the server might decide to send back XML when I didn't expect it.
A more pressing concern would be why the 404 errors are being detected for only SOME of the requests. In 559 requests, the items producing a 404 error are 77, 232, 235, 238, 246, 275, etc... so the service or client is just failing on random requests.
Edit (2014-02-25 12:20 EST):
It appears as if ALL of the files that failed (404 error) were text-based. For example...
Example Request Header (session #560):
POST http://localhost:50205/Files/Put/060C976372174F51BEB84FE524E57C57/1931975CE8E1090A6D66738A560888AD/1426/AssemblyInfo.cs HTTP/1.1
Content-Type: multipart/form-data;
Accept: application/json
Host: localhost:50205
Transfer-Encoding: chunked
Expect: 100-continue
592
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Utility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Utility")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1071992e-2d4c-49df-9526-6d4d29f979b4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
0
Example Response Header (session #560):
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B?RDpcX1NvdXJjZVxGSUwwMVx0cnVua1xTcG90bGVzc1xGcmFtZXdvcmtzXEZpbGVNYW5hZ2VtZW50XFByb2plY3RzXEZNRi5TdG9yYWdlU2VydmVyLkhvc3RpbmcuUHVibGljXEZpbGVzXFB1dFwwNjBDOTc2MzcyMTc0RjUxQkVCODRGRTUyNEU1N0M1N1wxOTMxOTc1Q0U4RTEwOTBBNkQ2NjczOEE1NjA4ODhBRFwxNDI2XEFzc2VtYmx5SW5mby5jcw==?=
X-Powered-By: ASP.NET
Date: Tue, 25 Feb 2014 15:24:10 GMT
Connection: close
Content-Length: 5106
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 8.0 Detailed Error - 404.7 - Not Found</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 5px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;word-break:break-all;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px;
font-weight:bold;font-size:1em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif;
color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF;
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal;
font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;}
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;}
-->
</style>
</head>
<body>
<div id="content">
<div class="content-container">
<h3>HTTP Error 404.7 - Not Found</h3>
<h4>The request filtering module is configured to deny the file extension.</h4>
</div>
<div class="content-container">
<fieldset><h4>Most likely causes:</h4>
<ul> <li>Request filtering is configured for the Web server and the file extension for this request is explicitly denied.</li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Things you can try:</h4>
<ul> <li>Verify the configuration/system.webServer/security/requestFiltering/fileExtensions settings in applicationhost.config and web.config.</li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Detailed Error Information:</h4>
<div id="details-left">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Module</th><td> RequestFilteringModule</td></tr>
<tr><th>Notification</th><td> BeginRequest</td></tr>
<tr class="alt"><th>Handler</th><td> ServiceStack.Factory</td></tr>
<tr><th>Error Code</th><td> 0x00000000</td></tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Requested URL</th><td> http://localhost:50205/Files/Put/060C976372174F51BEB84FE524E57C57/1931975CE8E1090A6D66738A560888AD/1426/AssemblyInfo.cs</td></tr>
<tr><th>Physical Path</th><td> D:\_Source\FIL01\trunk\Spotless\Frameworks\FileManagement\Projects\FMF.StorageServer.Hosting.Public\Files\Put\060C976372174F51BEB84FE524E57C57\1931975CE8E1090A6D66738A560888AD\1426\AssemblyInfo.cs</td></tr>
<tr class="alt"><th>Logon Method</th><td> Not yet determined</td></tr>
<tr><th>Logon User</th><td> Not yet determined</td></tr>
<tr class="alt"><th>Request Tracing Directory</th><td> C:\Users\Fred\Documents\IISExpress\TraceLogFiles\FMF.STORAGESERVER.HOSTING.PUBLIC</td></tr>
</table>
<div class="clear"></div>
</div>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>More Information:</h4>
This is a security feature. Do not change this feature unless the scope of the change is fully understood. If the file extension for the request should be allowed, remove the denied file extension from configuration/system.webServer/security/requestFiltering/fileExtensions.
<p>View more information »</p>
</fieldset>
</div>
</div>
</body>
</html>
Edit (2014-02-25 14:27 EST):
Continuing to test and finding that ServiceStack ignoring the Accept header IS a bigger problem than I hoped. Since all files must be persisted, and since those files must include both HTML and XML files, I need to ensure ServiceStack only sends back the response that was requested. Some of the files sent in my last test included HTML files and, quite unfortunately, ServiceStack sent back an HTML document as the response.
The temp folder contains a bunch of random files. And, as you might expect, because I have a ton of source files on hand, the temp folder includes a few C#/VS2K12 solutions. For example, I copied in the source of DoFactory's solution and several of its .Config, .cs, .csproj files fail while others of the same type go through.
The DTO being used...
//[Route("/Files/Put/{Token}/{Checksum}/{SizeBytesText}/{FileNameOrExtension}", "POST")]
[Route("/Files/Put/{PathInfo*}", "POST")]
public class PutFileRequest : IReturn<PutFileResponse>, IRequiresRequestStream
{
public string Token { get; set; }
public string Checksum { get; set; }
public string SizeBytesText { get; set; }
public string FileNameOrExtension { get; set; }
public System.IO.Stream RequestStream { get; set; }
}
I've intentionally included the original route I was using. Note that the URI is constructed using a set of variables and the name of the file. The name of the file is used for convenience on the server to allow the file to be persisted using the original file extension.
Below is the Main method from a test app which fails consistently. Any attempt to post this file will cause a 404 error. Note that the file is intact and that the FileSteam is able to open and copy the contents of the file successfully. Had a problem existed with the file then this should have failed.
static void Main(string[] args)
{
var filePath = #"D:\Temp\_Source\DoFactory\CS_4.5\Spark\Art.Web\Areas\Shop\Models\ProductsModel.cs";
var fileInfo = Files.GetInfo(filePath, calculateChecksum: true);
var uri = #"http://localhost:50205/Files/Put/" +
Guid.NewGuid().ToString("N") + "/" +
fileInfo.Checksum + "/" +
fileInfo.SizeBytes.Value + "/" +
System.IO.Path.GetFileName(filePath);
var client = (HttpWebRequest) WebRequest.Create(uri);
client.Method = WebRequestMethods.Http.Post;
client.AllowWriteStreamBuffering = false;
client.SendChunked = true;
client.ContentType = "multipart/form-data;";
client.Timeout = int.MaxValue;
client.Accept = "application/json";
using (FileStream fileStream = File.OpenRead(filePath))
{
fileStream.CopyTo(client.GetRequestStream());
}
var responseString = string.Empty;
try { responseString = new StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (String.IsNullOrWhiteSpace(responseString)) { Environment.Exit(1); }
PutFileResponse response = null;
try { response = responseString.FromJson<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
if (response == null)
{
try { response = responseString.FromXml<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
if (response == null)
{
try { response = responseString.FromJsv<PutFileResponse>(); }
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
if (response == null) { Environment.Exit(2); }
Console.ReadLine();
}
After a day+ of testing, and somewhere around 1,000 tests, I have found a way around the problem. However, in the findings leave me with a request to the ServiceStack team to find a way around this.
If a file is posted to a path which appears to contain a file name at the end, ServiceStack will respond with a result matching the contents of the item contained within the RequestStream. If the item is HTML the response will be an HTML response. If the item is XML the response will be an XML response. In these scenarios the Accept header is always ignored.
To navigate around this problem I have broken the filename into separate parts within the URL. A path that would originally resolve as:
http://localhost:1234/Files/Put/ABC123/MyFile.xml
... is now posting as this ...
http://localhost:1234/Files/Put/ABC123/F/MyFile/X/xml
... or, if I just need the extension, the parts of the extension are broken ...
http://localhost:1234/Files/Put/ABC123/X/tar/gz
In these examples, the service knows how to reassemble the file name and/or extension.
The end result to this change is that XML and HTML files are posted, as expected, and ServiceStack obeys the Accept header. In all tests after this change ServiceStack responded with the needed JSON object. Additionally, no 404 errors are encountered.

How to make Y.io's global events broadcast across instances

I would like to listen for all io request in all my web pages, however, when I used the syntax below, I can ONLY listen for the io with the yui instance.
Y.on('io:success', myCallBack);
How can I write a custom method/event or something else to achieve this?
My question is actually the same as below URL:
http://yuilibrary.com/forum/viewtopic.php?p=26009
I googled for a while but did not find a practical answer for this, any help will be appreciated, thanks.
Try
(Y.io._map['io:0'] || new Y.IO()).publish({
'io:success': { broadcast: 2 },
'io:complete': { broadcast: 2 },
etc.
});
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>io.jsp</title>
<script src="/spring-test/scripts/yui_3.5.1/build/yui/yui-min.js"></script>
</head>
<body>
test
<script>
YUI().use("io-base", function(Y){
function onSuccess(transactionid,response,arguments){
alert('start!');
}
Y.Global.on('io:start',onSuccess);
});
Y1 = YUI().use("io-base", "node", function(Y1){
Y1.publish('io:start',{broadcast : 2});
Y1.io("http://www.yahoo.com.hk");
});
</script>
</body>
Finally I got one example , however it works only on FF, Chrome but fail in IE:
Please suggest if there is any improvement, thanks.

Resources