Remotely Calling The Google Search Appliance RESTful Web Services When SAML is enabled
June 23rd, 2009
Calling the Google Search Appliance when a SAML interface or Forms Authentication security interface is enabled causes a bit of a challenge from SharePoint or ASP.NET. The following is some code that we developed to handle all of the hand shaking from the redirects and cookie exchange. This will be published shortly as a open source project.
public string SecureSearch(string term)
{
try
{
StringBuilder defaultquery = new StringBuilder();
defaultquery.Append(ConfigurationManager.AppSettings["GSADEVICEURL"]);
defaultquery.Append("/search?q=" + term);
defaultquery.Append("&client=" + ConfigurationManager.AppSettings["GSAFRONTEND"]);
defaultquery.Append("&output=xml_no_dtd");
defaultquery.Append("&site=" + ConfigurationManager.AppSettings["GSACOLLECTION"]);
defaultquery.Append("&access=a");
defaultquery.Append("&entqr=3&ud=1&oe=UTF-8&ie=UTF-8");
defaultquery.Append("&filter=" + ConfigurationManager.AppSettings["GSASEARCHFILTER"]);
defaultquery.Append("&num=" + ConfigurationManager.AppSettings["RESULTSPERPAGE"]);
Regex cookieCheck = new Regex("googlecookiecheck", RegexOptions.IgnoreCase);
log.Info("Step 1 Call GSA for secure query");
string loginurl = callGSA(defaultquery.ToString(), false);
//if the return url has the cookie check added, send the url back to the gsa
//the cookie check cookie will be attached
if (cookieCheck.Match(loginurl).Success)
{
//send the url returned with cookiecheck back to GSA
log.Info("Step 2 Call GSA for secure doc, respond to cookiecheck request");
loginurl = callGSA(ConfigurationManager.AppSettings["GSADEVICEURL"] + loginurl, false);
if (!gsaResultsReturned)
{
log.Info("Step 3 Call GSA for secure only with redirect from cookiecheck request");
loginurl = callGSA(ConfigurationManager.AppSettings["GSADEVICEURL"] + loginurl, false);
}
}
if (!gsaResultsReturned)
{
log.Info("Step 4 Call GSA to get result set");
loginurl = callGSA(loginurl, true);
}
log.Info("Step 5 COMPLETE");
}
catch (Exception ex)
{
log.Error("btnSearch_Click", ex);
}
return results.OuterXml.ToString();
}
private string callGSA(string url, bool allowredirect )
{
gsaResultsReturned = false;
string returnURL = string.Empty;
try
{
log.Error("callGSA() url ->" + url);
HttpWebRequest HttpWReq = (HttpWebRequest)WebRequest.Create(url);
HttpWReq.KeepAlive = true;
HttpWReq.Accept = "*/*";
HttpWReq.Headers.Add("Accept-Language", "en-us");
HttpWReq.Headers.Add("Accept-Encoding", "gzip, deflate");
HttpWReq.AllowAutoRedirect = allowredirect;
HttpWReq.CookieContainer = cookieC;
HttpWReq.Credentials = System.Net.CredentialCache.DefaultCredentials;
HttpWReq.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727)";
if (allowredirect)
{
HttpWReq.MaximumAutomaticRedirections = 10;
}
CookieCollection mycookies = HttpWReq.CookieContainer.GetCookies(new Uri(ConfigurationManager.AppSettings["GSACOOKIEURL"]));
HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse();
log.Info("......callGSA response http status = " + HttpWResp.StatusCode);
//get header collection
WebHeaderCollection col = HttpWResp.Headers;
if (HttpWResp.StatusCode.Equals(HttpStatusCode.Found))
{
//get location and make request
string[] redirectURL = col.GetValues("Location");
returnURL = redirectURL[0];
log.Debug("......callGSA() found redirect URL from GSA to->" + redirectURL[0]);
}
//logHeader(col);
CookieCollection csk = new CookieCollection();
csk = HttpWResp.Cookies;
for (int i = 0; i < csk.Count; i++)
{
log.Debug("............. callGSA response cookies " + csk[i].Name + " value " + csk[i].Value);
log.Debug("............. callGSA response cook domain " + csk[i].Domain);
log.Debug("............. callGSA response cook Path " + csk[i].Path);
log.Debug("............. callGSA response cook expires " + csk[i].Expires.ToLongTimeString());
log.Debug("............. callGSA response cook secure " + csk[i].Secure.ToString());
String[] values = col.GetValues("Set-Cookie");
if (null != values && values.Length > 0)
{
for (int j = 0; j < values.Length; j++)
{
Uri cookuri = new UriBuilder("http", csk[i].Domain, 80).Uri;
log.Info("......callGSA moving cookie " + cookuri.ToString() + " " + values[j]);
cookieC.SetCookies(cookuri, values[j]);
}
}
}
//this is the final step, we have a result set from the GSA
if (HttpWResp.StatusCode.Equals(HttpStatusCode.OK) ||
(returnURL.Equals(string.Empty)))
{
gsaResultsReturned = true;
Stream receiveStream = HttpWResp.GetResponseStream();
Encoding UTF8_Encoding = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(receiveStream, UTF8_Encoding);
//get the response and display
results.LoadXml(readStream.ReadToEnd());
}
}
catch (Exception ex)
{
log.Error("CallGSA ", ex);
}
return returnURL;
}



