FastCGI: retrieve the request headers - c++

I’m currently working on a Web C++ application using FastCGI with Apache and mod_fcgid.
I’m trying to retrieve the headers of a request, but I didn’t find how to do so. After some researches, I thought the headers were in the attribute “envp” of “FCGX_Request”, but it contains environment variables such as:
REMOTE_ADDR: 192.168.0.50
SERVER_SOFTWARE: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/1.0.0f DAV/2 mod_fcgid/2.3.6
REDIRECT_UNIQUE_ID: TxytP38AAAEAABpcDskAAAAE
FCGI_ROLE: RESPONDER
HTTP_ACCEPT_LANGUAGE: fr
SERVER_SIGNATURE: <address>Apache/2.2.21 [etc.]
These variables offer me useful informations, but I need the real HTTP headers, and especially “Cookie”. I tried to read on the stream “in” of the “FCGX_Request” but it seems to be for the request body (POST datas). As my application is intended to be multi-threaded, I use “FCGX_Accept_r()”, like this:
while(true)
{
FCGX_Init();
FCGX_Request* fcgiRequest = new FCGX_Request;
FCGX_InitRequest(fcgiRequest, 0, 0);
if(FCGX_Accept_r(fcgiRequest) < 0)
break;
Request* request = new Request(fcgiRequest);
request->process();
}
But actually, I don’t use threads. Requests are executed one after the other.
How can I get the request headers?
Thank you.

Try the following code. It should print out the entire environment so you can find the variable you are looking for.
while(true)
{
FCGX_Init();
FCGX_Request* fcgiRequest = new FCGX_Request;
FCGX_InitRequest(fcgiRequest, 0, 0);
if(FCGX_Accept_r(fcgiRequest) < 0)
break;
char **env = fcgiRequest->envp;
while (*(++env))
puts(*env);
Request* request = new Request(fcgiRequest);
request->process();
}

Related

Qt QNetworkAccessManager or other method get html status code without getting page contenet?

i need to get web sites html status codes
today i just do simple get request to the domain , and then i get the status code as part of the response , but also the site index.html content .
pNetworkManager = new QNetworkAccessManager(this);
reply = pNetworkManager->get(request);
QVariant vStatusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
data=reply->readAll();
this last function i like to avoid if it can be avoided ,
is there any way to get only the domain status code ?
Maybe you can send a HEAD request instead of a GET request?
This is not a Qt / client specific solution, but is the approach recommended by the HTTP protocol when you don't need the content, but just want to get the headers that a request would normally produce, for example in order to validate that the page exists.
I suppose this could be done with QNetworkAccessManager using the head() method
I agree with #shevron's answer, but if the site you're communicating with isn't "clever" enough to implement the HEAD request, you can still avoid the readAll() call.
QByteArray line = reply->readLine(); //< eg "HTTP/1.0 200 OK"
QList<QByteArray> chunks = line.split(' ');
QString statusCode = chunks[1];
That should avoid the memory overhead of readAll().

Parsing XML webservice and storing the data for presentation on a windows phone 7 device

I'm working on an app that requires extracting data from an xml web service, then I want to store that data (images+titles+datetime ...) to display it on my app then select an item and navigate to another page that displays more info about this item.
Is there a detailed tutorial that explains the parsing and storing process clearly (with the threads) because I'm gonna need it a lot for my app.Thanks!
I usually use this method, but didn't always get me what i want:
var doc = XDocument.Load(new StringReader(e.Result));
var items = from c in doc.Descendants("item")
select new RSSitem()
{
Title = c.Element("title").Value,
Photo = c.Element("img").Attribute("src").Value,
Description = c.Element("description").Value,
Link = c.Element("link").Value,
};
ListBoxNews.ItemsSource = items;
Sounds like you are in over your head (based on the vague nature of your question). So I'm offering my advise to get up to speed, so you can get started and ask a question that we can help give a definitive answer to.
With WP7 and .NET you shouldn't really have to do much manual parsing of Web Services. You should be able to add a Service Reference and generate a proxy which will handle this for you. This will also generate business objects for the data returned by your service.
Once you have that done, you can look into Windows Phone Navigation which should help you transition between pages in your application.
To consume web services:
String baseUri = “your service URI";
WebClient wc = new WebClient();
public MainPage()
{
InitializeComponent();
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_downloadstringcompleted);
// event handler that will handle the ‘downloadstringsompleted’ event
wc.DownloadStringAsync(new Uri(baseUri));
// this method will download your string URI asynchronously
}
void wc_downloadstringcompleted(Object sender, DownloadStringCompletedEventArgs e)
{
// method will get fired after URI download completes
// writes your every code here
}
To parse the data:
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
break;
case XmlNodeType.Text:
break;
case XmlNodeType.EndElement:
break;
}
}
}
}
To store in isolated storage: http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstoragesettings%28v=vs.95%29.aspx
For navigation:
NavigationService.Navigate(new Uri("/SecondPage.xaml?msg=" + navigationstring, UriKind.Relative));

IIS7 native module - setting request entity with file handle

So I'm working on an IIS7 native module, and part of what it will do is process some fairly large uploaded files. I'm trying to work on ways to reduce the memory footprint of the module while doing this.
One thing I was able to do with the processed response data, which is nice, is pass open file handles to the underlying system instead of memory buffers by using the HttpDataChunkFromFileHandle chunk types. I'm trying to do the same thing with the request data, but so far no joy.
What I am doing is first I am reading all of the request data, processing it, and then setting the entity chunks in the raw HTTP_REQUEST like this:
HTTP_REQUEST* rawRequest = _context->GetRequest()->GetRawHttpRequest();
rawRequest->EntityChunkCount = 1;
rawRequest->pEntityChunks = new HTTP_DATA_CHUNK[1];
rawRequest->pEntityChunks[0].DataChunkType = HttpDataChunkFromFileHandle;
rawRequest->pEntityChunks[0].FromFileHandle.FileHandle = _requestFile.handle();
rawRequest->pEntityChunks[0].FromFileHandle.ByteRange.StartingOffset.QuadPart = 0;
rawRequest->pEntityChunks[0].FromFileHandle.ByteRange.Length.QuadPart = _requestFile.size();
and returning RQ_NOTIFICATION_CONTINUE.
This results in a 403 response from the server.
If I use a memory chunk instead, it works correctly:
char* bufferOut = static_cast<char*>(_context->AllocateRequestMemory( _requestFile.size() ));
std::memcpy( bufferOut, _requestFile.map( 0, _requestFile.size() ), _requestFile.size() );
HTTP_REQUEST* rawRequest = _context->GetRequest()->GetRawHttpRequest();
rawRequest->EntityChunkCount = 1;
rawRequest->pEntityChunks = new HTTP_DATA_CHUNK[1];
rawRequest->pEntityChunks[0].DataChunkType = HttpDataChunkFromMemory;
rawRequest->pEntityChunks[0].FromMemory.pBuffer = (PVOID)bufferOut;
rawRequest->pEntityChunks[0].FromMemory.BufferLength = _requestFile.size()
So... is HttpDataChunkFromFileHandle just not supported for request entities? Or is there something else I need to do for it to work?
Do I need to set any specific security permissions on the file?

SBL-ODU-01007 The HTTP request did not contain a valid SOAPAction header

I am hoping someone can help get me in the right direction...
I am using Powerbuilder 12 Classic and trying to consume a Oracle CRM OnDemand web service.
Using Msxml2.XMLHTTP.4.0 commands, I have been able to connect using https and retrieve the session id, which I need to send back when I invoke the method.
When I run the code below, I get the SBL-ODU-01007 The HTTP request did not contain a valid SOAPAction header error message. I am not sure what I am missing??
OleObject loo_xmlhttp
ls_get_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=login"
try
loo_xmlhttp = CREATE oleobject
loo_xmlhttp.ConnectToNewObject("Msxml2.XMLHTTP.4.0")
loo_xmlhttp.open ("GET",ls_get_url, false)
loo_xmlhttp.setRequestHeader("UserName", "xxxxxxx")
loo_xmlhttp.setRequestHeader("Password", "xxxxxxx")
loo_xmlhttp.send()
cookie = loo_xmlhttp.getResponseHeader("Set-Cookie")
sesId = mid(cookie, pos(cookie,"=", 1)+1, pos(cookie,";", 1)-(pos(cookie,"=", 1)+1))
ls_post_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration/Activity;"
ls_response_text = "jsessionid=" + sesId + ";"
ls_post_url = ls_post_url + ls_response_text
loo_xmlhttp.open ("POST",ls_post_url, false)
loo_xmlhttp.setRequestHeader("COOKIE", left(cookie,pos(cookie,";",1)-1) )
loo_xmlhttp.setRequestHeader("COOKIE", left(cookie,pos(cookie,";",1)-1) )
ls_post_url2 = "document/urn:crmondemand/ws/activity/10/2004:Activity_QueryPage"
loo_xmlhttp.setRequestHeader("SOAPAction", ls_post_url2)
loo_xmlhttp.send()
ls_get_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=logoff"
loo_xmlhttp.open ("POST",ls_get_url, false)
loo_xmlhttp.send()
catch (RuntimeError rte)
MessageBox("Error", "RuntimeError - " + rte.getMessage())
end try
I believe you are using incorrect URL for Login and Logoff;
Here is the sample:
https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=login
https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=logoff
Rest of the code looks OK to me.
I have run into similar issues in PB with msxml through ole. Adding this may help:
loo_xmlhttp.setRequestHeader("Content-Type", "text/xml")
you need to make sure that the your value for ls_post_url2 is one of the values that is found in the wsdl file. Just search for "soap:operation soapAction" in the wsdl file to see the valid values for SOAPAction.

Sitecore Clear Cache Programmatically

I am trying to publish programmatically in Sitecore. Publishing works fine. But doing so programmatically doesn't clear the sitecore cache. What is the best way to clear the cache programmatically?
I am trying to use the webservice that comes with the staging module. But I am getting a Bad request exception(Exception: The remote server returned an unexpected response: (400) Bad Request.). I tried to increase the service receivetimeout and sendtimeout on the client side config file but that didn't fix the problem. Any pointers would be greatly appreciated?
I am using the following code:
CacheClearService.StagingWebServiceSoapClient client = new CacheClearService.StagingWebServiceSoapClient();
CacheClearService.StagingCredentials credentials = new CacheClearService.StagingCredentials();
credentials.Username = "sitecore\adminuser";
credentials.Password = "***********";
credentials.isEncrypted = false;
bool s = client.ClearCache(true, dt, credentials);
I am using following code to do publish.
Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Database web = Sitecore.Configuration.Factory.GetDatabase("web");
string userName = "default\adminuser";
Sitecore.Security.Accounts.User user = Sitecore.Security.Accounts.User.FromName(userName, true);
user.RuntimeSettings.IsAdministrator = true;
using (new Sitecore.Security.Accounts.UserSwitcher(user))
{
Sitecore.Publishing.PublishOptions options = new Sitecore.Publishing.PublishOptions(master, web,
Sitecore.Publishing.PublishMode.Full, Sitecore.Data.Managers.LanguageManager.DefaultLanguage, DateTime.Now);
options.RootItem = master.Items["/sitecore/content/"];
options.Deep = true;
options.CompareRevisions = true;
options.RepublishAll = true;
options.FromDate = DateTime.Now.AddMonths(-1);
Sitecore.Publishing.Publisher publisher = new Sitecore.Publishing.Publisher(options);
publisher.Publish();
}
In Sitecore 6, the CacheManager class has a static method that will clear all caches. The ClearAll() method is obsolete.
Sitecore.Caching.CacheManager.ClearAllCaches();
Just a quick note, in Sitecore 6.3, that is not needed anymore. Caches are being cleared automatically after a change happens on a remote server.
Also, if you are on previous releases, instead of clearing all caches, you can do partial cache clearing.
There is a free shared source component called Stager that does that.
http://trac.sitecore.net/SitecoreStager
If you need a custom solution, you can simply extract the source code from there.
I got this from Sitecore support. It clears all caches:
Sitecore.Context.Database = this.WebContext.Database;
Sitecore.Context.Database.Engines.TemplateEngine.Reset();
Sitecore.Context.ClientData.RemoveAll();
Sitecore.Caching.CacheManager.ClearAllCaches();
Sitecore.Context.Database = this.ShellContext.Database;
Sitecore.Context.Database.Engines.TemplateEngine.Reset();
Sitecore.Caching.CacheManager.ClearAllCaches();
Sitecore.Context.ClientData.RemoveAll();
Out of the box solution provided by Sitecore to clean caches (ALL of them) is utilized by the following page: http://sitecore_instance_here/sitecore/admin/cache.aspx and code behind looks like the following snippet:
foreach (var cache in Sitecore.Caching.CacheManager.GetAllCaches())
cache.Clear();
Via the SDN:
HtmlCache cache = CacheManager.GetHtmlCache(Context.Site);
if (cache != null) {
cache.Clear();
}