Overview
I want to be able to modify request parameters and content to 3rd party web services (ArcGIS Server). This will be used to create a security layer that exists between any client application and the server application.
I think that I have found a solution but I am current having some difficulties in the implementation.
Potential Solution: Modify Request with a Custom Request Filter
For the solution I implemented a custom request filter loosely based on the sample shown on MSDN. I have 'enhanced' the code so that I can search and replace the necessary content using regular expressions. This involves:
- Converting the content (stored in a byte array) into a string.
- Searching the string and performing any necessary modifications.
- Converting the modified string into a byte array and writing it to the buffer.
An example is shown below:
public override int Read(byte[] buffer, int offset, int count)
{
int bytesRead = _stream.Read(buffer, offset, count);
string orgContent = Encoding.UTF8.GetString(buffer, offset, bytesRead);
string orgContentDecoded = HttpUtility.UrlDecode(orgContent);
string layersPattern = @"&layers=(show|hide|include|exclude):([0-9]+,?)+";
Regex layersRegex = new Regex(layersPattern, RegexOptions.IgnoreCase);
string[] permittedLayers = new string[] { "0" , "1" };
string replacementLayers = "&layers=show:" + String.Join(",", permittedLayers);
string newContentDecoded = layersRegex.Replace(orgContentDecoded, replacementLayers);
string newContent = newContentDecoded.Replace(",", "%2C").Replace(":", "%3A");
byte[] newBuffer = Encoding.UTF8.GetBytes(newContent);
int newByteCountLength = Encoding.UTF8.GetByteCount(newContent);
Encoding.UTF8.GetBytes(newContent, 0, Encoding.UTF8.GetByteCount(newContent), buffer, 0);
return bytesRead;
}
This seems to work well so long as the modified content length is not different than the original content length. For instance, if I replace a 1 with a 2 everything works. However, if I replace a 1 with a 10 (thereby increasing the message size by 1) then I receive an error from ArcGIS Server that the format is unsupported.
This has brought two concerns to my attention:
- The current implementation does not handle chunked requests. That is, if the request sie is large enough Read may be called multiple times for a single request. How should chunking be handled in this scenario?
- What is the root cause of the error message? Is the problem related to the content length being different than the stream length? How do I correctly modify the content so that changing its length is not an issue?
Any thoughts?