Request relay webservice not logging in - c#

I've made this webservice which relays a request to another server. It takes a request that is made to it's own url, then does the request to a different url and responses the result back to it's client.
void Application_BeginRequest(object sender, EventArgs e)
{
// Setup destination url schemes
string newAuth = "localhost:1861";
string newUrl = "http://" + newAuth + Request.Url.PathAndQuery;
// Setup the request from this server to the other server
HttpWebRequest newRequest = (HttpWebRequest)WebRequest.Create(newUrl);
newRequest.AllowAutoRedirect = false;
// Copy all needed headers
List<string> copyHeaderNames = new List<string>()
{
"Accept-Encoding",
"Accept-Language",
"Upgrade-Insecure-Requests",
"Cache-Control",
"Connection",
"Cookie"
};
foreach (var key in copyHeaderNames)
{
try
{
if (newRequest.Headers.AllKeys.Contains(key))
{
newRequest.Headers[key] = Request.Headers[key].Replace(Request.Url.Authority, newAuth);
}
else
{
newRequest.Headers.Add(key, Request.Headers[key].Replace(Request.Url.Authority, newAuth));
}
}
catch { }
}
// Then setup the constant paramenters of the new request
newRequest.KeepAlive = Request.Headers["Connection"] == "keep-alive";
newRequest.Accept = Request.Headers["Accept"];
newRequest.Expect = Request.Headers["Expect"];
newRequest.UserAgent = Request.Headers["User-Agent"];
newRequest.ContentType = Request.ContentType;
newRequest.Method = Request.HttpMethod;
newRequest.Host = newAuth;
newRequest.Referer = newUrl;
// If the request is a POST, I need to copy the inputstream.
if (Request.HttpMethod == "POST")
{
byte[] inputBytes = ReadToByteArray(Request.InputStream);
string inputString = System.Text.Encoding.Default.GetString(inputBytes);
// Replace original url with destination url
inputString = inputString.Replace(Request.Url.Authority, newAuth);
inputBytes = System.Text.Encoding.Default.GetBytes();
Stream reqStream = newRequest.GetRequestStream();
reqStream.Write(inputBytes, 0, inputBytes.Length);
reqStream.Close();
}
// Then do the request
using (var resp = (HttpWebResponse)newRequest.GetResponse())
{
// Setup response paramenters
Response.StatusCode = (int)resp.StatusCode;
Response.StatusDescription = resp.StatusDescription;
// Get the response stream
using (var respstream = resp.GetResponseStream())
{
var res = ReadToByteArray(respstream);
// And respond it in the current response
Response.BinaryWrite(res);
// Then I copy all response headers to the current response
foreach (var key in resp.Headers.AllKeys)
{
try
{
// Replace the destination url back to the current url
string value = resp.Headers[key].Replace(newAuth, Request.Url.Authority);
if (Response.Headers.AllKeys.Contains(key))
{
Response.Headers[key] = value;
}
else
{
Response.Headers.Add(key, value);
}
}
catch { }
}
}
}
// Tell the program to end the request.
Response.End();
}
public static byte[] ReadToByteArray(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Now everything works except the login. The other website is a asp.net mvc4 application, it uses the standard Membership with authentication cookie.
Any ideas?

Guess copying the content of the request object doesn't exactly copy it. The solution was to go 1 layer down the OSI model to the TCP layer and do the relaying on that level.

Related

How to resolve 400 error with bad request in update api when it is deployed

I am getting 400 error code with bad request while request to file upload API.
I built the back-end and front-end for file uploading in asp.net core and it works in localhost when I run it with IIS in my PC (using visual studio 2017).
Both of saving and updating API are working in my local but update API is not working if I deploy the code
front-end code like below:
public static async Task<HttpResponseMessage> UploadFile(string uploadUrl, string filePath, FFFileInfo fileInfo)
{
string fileName = fileInfo.Name + "." + fileInfo.Extension;
string contentType = MimeTypes.GetMimeType(filePath);
using (var hc = new HttpClient())
{
hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(TokenType, AccessToken);
hc.DefaultRequestHeaders.Accept.Clear();
hc.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamContent streamContent = CreateFileContent(fileStream, fileName, contentType);
// StreamContent streamContent = CreateFileContent(fileStream, "image.jpg", "image/jpeg"); // Multiple file upload
var requestContent = new MultipartFormDataContent("Upload Id" + DateTime.Now.ToString(CultureInfo.InvariantCulture));
requestContent.Add(streamContent, fileInfo.Name, fileName);
var progressContent = new ProgressableStreamContent(
requestContent,
4096,
(sent, total) =>
{
//Console.WriteLine("Uploading {0}/{1}", sent, total);
int percentage = (int) Math.Round((double)(100 * sent) / total);
Console.Write("\r{0}\t{1}%", fileInfo.Path, percentage);
if (sent == total)
{
Console.WriteLine();
}
});
var response = await hc.PostAsync(new Uri(uploadUrl), progressContent);
return response;
}
}
backend code like below:
[HttpPost]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadFiles([FromQuery] FFFileInfo fileinfo)
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest($"Expected a multipart request, but got {Request.ContentType}");
}
authUser = User.ToAuthUser();
userId = authUser.UserId();
customerId = authUser.CustomerId();
Server.Model.File new_file = new Server.Model.File();
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
MemoryStream writeStream = new MemoryStream();
byte[] content = null;
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
int chunkSize = 1024;
byte[] byte_file = new byte[chunkSize];
int bytesRead = 0;
new_file.File_Content = byte_file;
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
//await section.Body.CopyToAsync(targetStream);
using (var byte_reader = new BinaryReader(section.Body))
{
do
{
bytesRead = byte_reader.Read(byte_file, 0, byte_file.Length);
if(bytesRead <= 0)
{
content = writeStream.ToArray();
}
writeStream.Write(byte_file, 0, bytesRead);
} while (bytesRead > 0);
content = writeStream.ToArray();
}
}
}
// Drains any remaining section body that has not been consumed and
// reads the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
try
{
new_file = new Server.Model.File
{
File_Name = fileinfo.Name,
File_Path = fileinfo.Path,
File_Ext = fileinfo.Extension,
Check_Sum = fileinfo.Checksum,
ToolSerialNumber = fileinfo.ToolSerialNumber,
FileSize = fileinfo.Length,
File_Content = content,
UserId = userId,
CustomerId = customerId
};
}
catch (Exception ex)
{
return BadRequest(ex);
}
try
{
if (!fileService.isExist(new_file.File_Path, userId))
{
fileService.SaveFile(new_file);
}
else
{
Server.Model.File existing = fileService.GetFileByPath(new_file.File_Path, userId);
fileService.UpdateFile(existing, new_file);
}
//set file content to null to response with small data
new_file.File_Content = null;
return Ok(new_file);
}
catch (Exception ex)
{
logger.LogError("DB action error {0}", ex.ToString());
return BadRequest(ex);
}
}
As you can see the above code, saving and updating are using same code but only updating is not working when it is deployed.
It is very strange for me.
I found the solution.
This code was deployed by my client I couldn't check the database that he deployed.
Based on researching and testing, I got an idea that might be related with permission issue.
So, we check it for db.
At the end, we found that current user has insert, delete, select permission but have not update permission.
After granting the update permission, it is working perfectly

Forward HTTP request to another server

I have the following code that receives webhook messages:
// Read posted data
string requestBody;
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
requestBody.Log();
// Attempt to forward request
context.CopyTo(Settings.Payments.Paypal.ScirraPaypalIPNEndpoint);
requestBody contains data which is logged. I then attempt to forward the request to another URL:
public static void CopyTo(this HttpContext source, string url)
{
var destination = (HttpWebRequest) WebRequest.Create(url);
var request = source.Request;
destination.Method = request.HttpMethod;
// Copy unrestricted headers
foreach (var headerKey in request.Headers.AllKeys)
{
if (WebHeaderCollection.IsRestricted(headerKey)) continue;
destination.Headers[headerKey] = request.Headers[headerKey];
}
// Copy restricted headers
if (request.AcceptTypes != null && request.AcceptTypes.Any())
{
destination.Accept = string.Join(",", request.AcceptTypes);
}
destination.ContentType = request.ContentType;
destination.Referer = request.UrlReferrer?.AbsoluteUri ?? string.Empty;
destination.UserAgent = request.UserAgent;
// Copy content (if content body is allowed)
if (request.HttpMethod != "GET"
&& request.HttpMethod != "HEAD"
&& request.ContentLength > 0)
{
using (var destinationStream = destination.GetRequestStream())
{
request.InputStream.Position = 0;
request.InputStream.CopyTo(destinationStream);
destinationStream.Close();
}
}
if (!Settings.Deployment.IsLive)
{
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => true;
}
using (var response = destination.GetResponse() as HttpWebResponse)
{
if (response == null) throw new Exception("Failed to post to " + url);
}
}
The handler that receives this forwarded request has the code:
public void ProcessRequest(HttpContext context)
{
string requestBody;
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
requestBody.Log();
}
However on the handler forwarded to, requestBody is always empty! What am I doing wrong here?
Both servers are hosted in Clouflare, when posting from one to the other I get a CF 1000 prohibited IP error.
Solution is to add target servers IP address into requesting servers hosts file.

Http post method hanging before getting response using c# [duplicate]

Failed to get response for large file HTTP put create file using c#
I am using file watcher service service monitor, when user created file or folder we are uploading to cloud
if file size more than 512 MB it is taking too much time to get the response
here I am confusing here the issue with my code or server
and reason for this error
if any changes on my code suggest me.
{
var fileFolderObj1 = new FileFolder();
var postURL = apiBaseUri + "/filefolder/create/file/user/" + userId; // +"?type=file";
code = HttpStatusCode.OK;
HttpWebResponse response = null;
FileInfo f = new FileInfo(filePath);
long filesizeF = f.Length;
try
{
string selectedFile = null;
selectedFile = filePath;
var fi = System.IO.Path.GetFileName(filePath);
////commented for some reason
var postParameters = new Dictionary<string, object>();
postParameters.Add("file", new FileParameter(filePath, ""));
postParameters.Add("parentId", parentId);
postParameters.Add("newName", fi);
postParameters.Add("cloudId", cloudId);
postParameters.Add("isSecure", isSecure);
//postParameters.Add("fileSize", fi.Length);
postParameters.Add("fileSize", filesizeF);
var userAgent = "Desktop";
var formDataBoundary = "----WebKitFormBoundary" + DateTime.Now.Ticks.ToString("x");
var uri = new Uri(postURL);
var createFileRequest = WebRequest.Create(uri) as HttpWebRequest;
this.SetBasicAuthHeader(createFileRequest, userId, password);
createFileRequest.ContentType = "multipart/form-data";
createFileRequest.Method = "PUT";
createFileRequest.Timeout = System.Threading.Timeout.Infinite;
createFileRequest.KeepAlive = false;/*true;*/
createFileRequest.UserAgent = userAgent;
createFileRequest.CookieContainer = new CookieContainer();
try
{
using (var requestStream = createFileRequest.GetRequestStream())
{
}
using (response = (HttpWebResponse)createFileRequest.GetResponse())
{
StreamReader(response.GetResponseStream()).ReadToEnd();
fileFolderObj1 = JsonConvert.DeserializeObject<FileFolder>(reslut);
}
}
catch (Exception exc)
{
if (response != null)
{
code = response.StatusCode;
}
}
}
catch (Exception exc)
{
}
}
}
private static readonly Encoding encoding = Encoding.UTF8;
private void WriteMultipartFormData(Dictionary<string, object> postParameters, string boundary, Stream requestStream, ILogService logService = null)
{
var needsCLRF = false;
foreach (var param in postParameters)
{
// Skip it on the first parameter, add it to subsequent parameters.
if (needsCLRF)
{
requestStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
}
needsCLRF = true;
if (param.Value is FileParameter)
{
var fileToUpload = (FileParameter)param.Value;
// Add just the first part of this param, since we will write the file data directly to the Stream
var header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n",
boundary,
param.Key,
fileToUpload.FileName ?? param.Key,
fileToUpload.ContentType ?? "application/octet-stream");
requestStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
FileStream fileStream = new FileStream(fileToUpload.FileName, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0,buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
logService.Debug("WRITEMULTIPART FORM DATA Bufferlent Running :{0}", bytesRead);
}
fileStream.Close();
}
else
{
var postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
requestStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
var footer = "\r\n--" + boundary + "--\r\n";
requestStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
}
}

Getting Images from S3

I need to retrieve images from S3. I can't make the folder public and I cant use presigned URL's so all I am left with is GetObject();. Now the image that I'll get back has to be set as a source for an Iframe. To do that I am using a HttpWebHandler. The issue is that if i retrieve a html page it is working fine. But when I try to get an image back, all i get is junk data. Here is my code:
public void ProcessRequest(HttpContext context)
{
NameValueCollection appConfig = ConfigurationManager.AppSettings;
_accessKeyId = appConfig["AWSAccessKey"];
_secretAccessKeyId = appConfig["AWSSecretKey"];
S3 = new AmazonS3Client(_accessKeyId, _secretAccessKeyId);
string responseBody = "";
var request = new GetObjectRequest()
.WithBucketName(bucketName).WithKey("020/images/intro.jpg");
var responseHeaders = new ResponseHeaderOverrides
{
ContentType = "image/jpeg"
};
request.ResponseHeaderOverrides = responseHeaders;
using (var response = S3.GetObject(request))
{
using (var responseStream = response.ResponseStream)
{
using (var reader =
new StreamReader(responseStream))
{
responseBody = reader.ReadToEnd();
}
}
}
context.Response.Write(responseBody);
context.Response.Flush();
context.Response.End();
}
}
There are a couple of problems here:
You are setting the Content-Type on the response coming back from amazon, but not on the response from your application
You are using a StreamReader to read the content of the stream as text and then writing it back as text
Try this instead:
using (var response = S3.GetObject(request))
{
using (var responseStream = response.ResponseStream)
{
context.Response.ContentType = "image/jpeg";
var buffer = new byte[8000];
int bytesRead = -1;
while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
context.Response.OutputStream.Write(buffer, 0, bytesRead);
}
}
}
context.Response.End();

Problem when sending a webrequest

I use the following method to retrieve something from a webservice using a HTTPWebRequest:
private void RetrieveSourceCode(Method method)
{
try
{
String url = "http://123.123.123.123:8080/";
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(url), "Basic", new NetworkCredential("user", "pwd"));
HttpWebRequest request =(HttpWebRequest)WebRequest.Create("http://abc.abc.ch:8080/famixParser/projects/argouml/org.argouml.uml.ui.behavior.common_behavior.ActionAddSendActionSignal.doIt(java.util.Collection)");
Console.WriteLine(request.RequestUri.ToString());
request.Credentials = myCache;
request.Accept = "text/plain";
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (Exception e)
{
Console.WriteLine("exception when sending query: ");
throw e;
}
Stream resStream = response.GetResponseStream();
byte[] buf = new byte[8192];
StringBuilder sb = new StringBuilder();
string tempString = null;
int count = 0;
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.ASCII.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
String sourceCode = sb.ToString();
method.setSourceCode(sourceCode);
Console.WriteLine(sourceCode);
request.Abort();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Now I always get a 401 - Access denied exception. I don't know why, because if i use the same URL in my webbrowser, it works. Is it maybe because of the parantheses?
Please note: I changed the server address here, so its not working here, but I had to do it for confidentiality reasons.
You cache url and request url are different, I would think that means your username and password aren't being passed in the request.
String url = "http://123.123.123.123:8080/";
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(url), "Basic", new NetworkCredential("user", "pwd"));
uses 123.123
HttpWebRequest request =(HttpWebRequest)WebRequest.Create("http://abc.abc.ch:8080/famixParser/projects/argouml/org.argouml.uml.ui.behavior.common_behavior.ActionAddSendActionSignal.doIt(java.util.Collection)");
uses abc.ch

Categories

Resources