Cannot access google trends using HttpClient - httpclient

I'm kind of newbie to this...Basicly I need to run a script to download .csv files from google trends. I wrote the following code according to this reference , the code is like:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://www.google.com/accounts/ClientLogin");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>;
nameValuePairs.add(new BasicNameValuePair("Email", "myEmail"));
nameValuePairs
.add(new BasicNameValuePair("Passwd", "myPasswd"));
nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
nameValuePairs.add(new BasicNameValuePair("source",
"Google-cURL-Example"));
nameValuePairs.add(new BasicNameValuePair("service", "xapi"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
System.out.println(line);
if (line.startsWith("SID=")) {
String key = line.substring(4);
// Do something with the key
} catch (Exception e) {
}
I got the information about SID, LSID, Auth, but don't know how to use these information. I guess I should add these cookies in my following request, but don't know exactly how. I wrote another piece of code to connect to the certain URL, but I keep getting this message "You must be signed in to export data from Google Trends." The code is here if it helps:
URL url = new URL(myUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(true);
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.addRequestProperty("Authorization", "SID"+key);
conn.addRequestProperty("Email", "myEmail");
conn.addRequestProperty("Passwd", "myPasswd");
conn.setReadTimeout(5000);
conn.connect();
I searched around and found few useful information, anyone could help?

Does it have to be in Java? In python, it's as simple as this:
from pyGTrends import pyGTrends
connector = pyGTrends('google username','google password')
connector.download_report(('keyword1', 'keyword2'))
print connector.csv()
You'll need the google trends api library.
If it has to be Java, you may want to look at the HttpClient examples from Apache. "Form based logon" and "client authentication" may both be relevant.

I have just coded this:
https://github.com/elibus/j-google-trends-api
It is an unofficial Java implementation of Google Trends API. You could use it to easily access Google Trends or you might want to have a look at the code to see it works.
Anyway the authentication flow works as follows (all the steps are required):
Fetch https://accounts.google.com/ServiceLoginAuth and parse the GALX id
Post username/password + GALX
Get http://www.google.com
Then you can access Google Trend with relaxed QoS policies for authenticated users.

Related

How to call SSRS Rest-Api V1.0 with custom security implemented (NOT SOAP)

I have implemented the custom security on my reporting services 2016 and it displays the login page once the URL for reporting services is typed on browser URL bar (either reports or reportserver)
I am using the following code to pass the Credentials
when i use the code WITHOUT my security extension it works and looks like this
ICredentials _executionCredentials;
CredentialCache myCache = new CredentialCache();
Uri reportServerUri = new Uri(ReportServerUrl);
myCache.Add(new Uri(reportServerUri.GetLeftPart(UriPartial.Authority)),
"NTLM", new NetworkCredential(MyUserName, MyUserPassword));
_executionCredentials = myCache;
when i use the code WITH the security extension it doesnt work and looks like this
ICredentials _executionCredentials;
CredentialCache myCache = new CredentialCache();
Uri reportServerUri = new Uri(ReportServerUrl);
myCache.Add(new Uri(reportServerUri.GetLeftPart(UriPartial.Authority)),
"Basic", new NetworkCredential(MyUserName, MyUserPassword));
_executionCredentials = myCache;
and i get an Exception saying "The response to this POST request did not contain a 'location' header. That is not supported by this client." when i actually use this credentials
Is "basic" the wrong option ?
Have anyone done this ?
Update 1
Well it turns out that my SSRS is expecting an Authorisation cookie
which i am unable to pass (according to fiddler, there is no cookie)
HttpWebRequest request;
request = (HttpWebRequest)HttpWebRequest.Create("http://mylocalcomputerwithRS/Reports_SQL2016/api/v1.0");
CookieContainer cookieJar = new CookieContainer();
request.CookieContainer = cookieJar;
Cookie authCookie = new Cookie("sqlAuthCookie", "username:password");
authCookie.Domain = ".mydomain.mylocalcomputerwithRS";
if (authCookie != null)
request.CookieContainer.Add(authCookie);
request.Timeout = -1;
HttpWebResponse myHttpWebResponse = (HttpWebResponse)request.GetResponse();
That's how I got it (SSRS 2017; api v2.0). I took the value for the "body" from Fiddler:
var handler = new HttpClientHandler();
var httpClient = new HttpClient(handler);
Assert.AreEqual(0, handler.CookieContainer.Count);
// Create a login form
var body = new Dictionary<string, string>()
{
{"__VIEWSTATE", "9cZYKBmLKR3EbLhJvaf1JI7LZ4cc0244Hpcpzt/2MsDy+ccwNaw9hswvzwepb4InPxvrgR0FJ/TpZWbLZGNEIuD/dmmqy0qXNm5/6VMn9eV+SBbdAhSupsEhmbuTTrg7sjtRig==" },
{"__VIEWSTATEGENERATOR", "480DEEB3"},
{ "__EVENTVALIDATION", "IS0IRlkvSTMCa7SfuB/lrh9f5TpFSB2wpqBZGzpoT/aKGsI5zSjooNO9QvxIh+QIvcbPFDOqTD7R0VDOH8CWkX4T4Fs29e6IL92qPik3euu5QpidxJB14t/WSqBywIMEWXy6lfVTsTWAkkMJRX8DX7OwIhSWZAEbWZUyJRSpXZK5k74jl4x85OZJ19hyfE9qwatskQ=="},
{"txtUserName", "User"},
{"txtPassword", "1"},
{"btnLogin","Войти"}
};
var content = new FormUrlEncodedContent(body);
// POST to login form
var response = await httpClient.PostAsync("http://127.0.0.1:777/ReportServer/Logon.aspx", content);
// Check the cookies created by server
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var cookies = handler.CookieContainer.GetCookies(new Uri("http://127.0.0.1:777/ReportServer"));
Assert.AreEqual("sqlAuthCookie", cookies[0].Name);
// Make new request to secured resource
var myresponse = await httpClient.GetAsync("http://127.0.0.1:777/Reports/api/v2.0/Folders");
var stringContent = await myresponse.Content.ReadAsStringAsync();
Console.Write(stringContent);
As an alternative you can customize SSRS Custom Security Sample quite a bit.
I forked Microsoft's Custom Security Sample to do just what you are describing (needed the functionality at a client long ago and reimplemented as a shareable project on GitHub).
https://github.com/sonrai-LLC/ExtRSAuth
I created a YouTube walkthrough as well to show how one can extend and debug SSRS security with this ExtRSAuth SSRS security assembly https://www.youtube.com/watch?v=tnsWChwW7lA
TL; DR; just bypass the Microsoft example auth check in Login.aspx.cs and put your auth in Page_Load() or Page_Init() event of Login.aspx.cs- wherever you want to perform some custom logging check- and then immediately redirect auth'd user to their requested URI.

Can any body share me java code to make a one Rest api call to IBM BPM Cloud

Can any body share a java client code which makes a Rest calls to IBM Cloud BPM. Basically I want to know how to authenticate IBM Cloud BPM.
I tried the following code but it is not working
String user_info_url="https://ustrial01.bpm.ibmcloud.com/bpm/dev/rest/bpm/wle/v1/user/current?includeInternalMemberships=true&parts=all";
logger.info("user_info_url :" + user_info_url);
HttpClient client = HttpClientBuilder.create().build();
HttpGet get = new HttpGet(user_info_url);
String authData = "rajesh.kohir123#gmail.com" + ":" + "password";
String encoded = new sun.misc.BASE64Encoder().encode(authData .getBytes());
get.setHeader("Content-Type", "application/json");
get.setHeader("Accept", "application/json");
get.setHeader("Authorization", "Basic " + encoded);
HttpResponse cgResponse = client.execute(get);
if(cgResponse.getStatusLine().getStatusCode() != 200) {
logger.info("IBM Rest call failed");
}
if(cgResponse.getStatusLine().getStatusCode() == 200) {
logger.info("IBM Rest call Succeded");
String content = EntityUtils.toString(cgResponse.getEntity());
logger.info(content);
}
Any help is greatly appreciated
I ran your code and just made the changes in URL. It worked. I hope this helps you.
Following is the URL I used to execute an exposed service :
https://vhost031.bpm.ibmcloud.com/bpm/dev/rest/bpm/wle/v1/service/OMS#Greetings
I used the following code to add the parameters :
String parameters = "{'name':'pramod'}";
URIBuilder builder = new URIBuilder("https://vhost031.bpm.ibmcloud.com/bpm/dev/rest/bpm/wle/v1/service/OMS#Greetings");
List nameValuePairs = new ArrayList();
nameValuePairs.add(new BasicNameValuePair("action", "start"));
nameValuePairs.add(new BasicNameValuePair("params", parameters));
nameValuePairs.add(new BasicNameValuePair("createTask", "false"));
nameValuePairs.add(new BasicNameValuePair("parts", "all"));
builder.setParameters(nameValuePairs);
HttpGet get = new HttpGet(builder.build());
Download the download.zip form the post.
Look at the SampleBPDProcessTests.java - Line no 103
JSONObject results = bpmClient.runBPD(BPD_ID, PROCESS_APP_ID, bpdArgs);
The actual Java Code for Rest call is available as part of "bpm-rest-client.jar"
Try this concept.
Sample Java code to start a process:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://ustrial03.bpm.ibmcloud.com:443/bpm/dev/rest/bpm/wle/v1/process?
processAppId=3u092jr02j-djaodaj.u092302c166c1&bpdId=25.jklaklaa-539a-4150-
b63e-9ef94e96e521&action=start")
.put(null)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("Accept", "application/json")
.addHeader("Connection", "keep-alive")
.addHeader("Authorization", "Basic YXJrYX24223232hQGRlbG9pdHRlLmNvbTpkZWZjb240QA==")
.addHeader("Cache-Control", "no-cache")
.addHeader("Postman-Token", "f46c1525-7a75-954c-9265-bb2b21a57f16")
.build();
Response response = client.newCall(request).execute();
A full explanation of REST integration with BPM Cloud can be found in my answer at:
How to run IBM BPM Rest api call from Post man client

How to run Sharepoint Rest API from server side with elevated privileges?

The Sharepoint Rest API uses a simple URL of the type http://mysite/_api/search/query?querytext='search_key' to return search results as an XML. When I run this directly in a browser, I see a valid XML response:
(1) Am I right in assuming the above response is generated using the current user's authorization?
(2) Can this URL be invoked from server side? I tried it in a web method (WCF web service), but received a 401 - Unauthorized:
public string GetSearchResults(string searchKey)
{
string webURL = SPContext.Current.Web.Url;
string searchURL = webURL + "/_api/search/query?querytext='" + searchKey + "'";
WebClient client = new WebClient();
string xmlResponse = client.DownloadString(searchURL); // throws 401
// parse xmlResponse and return appropriately
}
(3) What I really need is to be able to get the search results irrespective of the current user's access rights (the requirement is that users will see all search results, with an option to "request access" when needed).
I tried this in the above web method, but it still throws the same 401:
public string GetSearchResults(string searchKey)
{
string webURL = SPContext.Current.Web.Url;
string searchURL = webURL + "/_api/search/query?querytext='" + searchKey + "'";
string xmlResponse;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
WebClient client = new WebClient();
xmlResponse = client.DownloadString(searchURL); // still 401
});
// parse xmlResponse and return appropriately
}
What is the right way to invoke the Rest URL from server side? Specifically, from a web method? And how can it be run as super user?
In order to perform REST request, authenticate the request via WebClient.Credentials Property
On Premise (your scenario)
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName,password,domain);
SharePoint Online
WebClient client = new WebClient();
client.Credentials = new SharePointOnlineCredentials(username,securedPassword);
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
Search results are always security trimmed by SharePoint so to make this work, you'd need to run your query after specifying new credentials as mentioned by Vadim. This is almost certainly not a good idea. If you're running code server side already, don't use the REST interface, just query directly using the search API.

Must/can I install MS ASP.NET Web API Client Libraries in order to post data to my Web API server?

Do I need to install ASP.NET Web API Client Libraries (as this article indicates) in order to post data to a Web API server? If so, can I do so in Visual Studio 2008 from a Windows CE project?
The reasons I wonder are:
0) The client is a Windows CE project, for which I'm using Visual Studio 2008, and I don't know if ASP.NET Web API Client Libraries are available for that version; I know I don't have the NuGet Package Manager in that environment.
1) I am successfully querying data from my RESTful Web API methods without installing ASP.NET Web API Client Libraries, using code like this:
while (true)
{
deptList.departments.Clear();
string uri = String.Format("http://platypi:28642/api/Duckbills/{0}/{1}", lastIdFetched, RECORDS_TO_FETCH);
var webRequest = (HttpWebRequest) WebRequest.Create(uri);
webRequest.Method = "GET";
using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
var reader = new StreamReader(webResponse.GetResponseStream());
string jsonizedDuckbills = reader.ReadToEnd();
List<Duckbill> duckbills = JsonConvert.DeserializeObject<List<Duckbill>>(jsonizedDuckbills);
if (duckbills.Count <= 0) break;
foreach (Duckbill duckbill in duckbills)
{
duckbillList.duckbills.Add(duckbill);
lastIdFetched = duckbill.Id;
}
} // if ((webResponse.StatusCode == HttpStatusCode.OK)
} // using HttpWebResponse
int recordsAdded = LocalDBUtils.BulkInsertDuckbills(duckbillList.duckbills);
totalRecordsAdded += recordsAdded;
} // while (true);
I'm stuck on posting, though, and the cleanest example I've seen so far for doing so is at that link already shown above.
I got an answer to my question on how to post here, but that hasn't made me smart enough yet to actually accomplish it. It's a step in the right direction, perhaps, although I reckon, based on how my client query code looks, that the client posting code would be of similar "style" (like the previously referenced article here, and unlike the likewise previously referenced answer here).
UPDATE
If I'm already providing the data in the uri string itself, as I am, like this:
string uri = String.Format("http://shannon2:28642/api/Departments/{0}/{1}", onAccountOfWally, moniker);
...why would I need to also specify it in postData? Or could I set postData (if that's just a necessary step to get the length) to those values...something like:
postData = String.Format("{0}, {1}", onAccountOfWally, moniker);
?
To talk to ASP.NET Web API, you do not necessarily need the client library, although it makes the life easier. After all, one of the benefits of HTTP services is the platform reach. Literally you can use any library that gives you HTTP capabilities. So, using WebRequest, you can do something like this. I'm using JSON in the payload. You can use XML and application/www-form-urlencoded as well. Just that you need to format the request body accordingly. Also, for complex objects, you will be better off using JSON.NET unlike formatting the JSON manually.
var request = System.Net.WebRequest.Create("http://localhost:12345/api/values");
request.Method = "POST";
string postData = "{\"firstName\":\"Steven\"," + "\"lastName\":\"Waugh\"}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/json";
request.ContentLength = byteArray.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(byteArray, 0, byteArray.Length);
}
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var reader = new System.IO.StreamReader(responseStream))
{
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
}
}
}
EDIT
If you are specifying data in URI, you do not need to specify the same in the request body. To let web API bind the parameters for you from URI, you will need to specify the route accordingly so that the placeholders are set for onAccountOfWally and moniker. Then you will need to use a simple type like string as action method parameters for web API to bind. By default, simple types are bound from URI path and query string and complex types from request body.

Invoking REST API for making new component in JIRA

I've to make a new Component in JIRA
I found out the POST url /rest/api/2/component for making new component, but i'm unable to know what type of inputs to be given.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("http://localhost:8080/rest/api/2/component/");
String authorization = JiraRequestResponseUtil.conversionForAuthorization();
postRequest.setHeader("Authorization", authorization);
StringEntity input = new StringEntity("\"name\":\"Component 1\",\"description\":\"This is a TEST JIRA component\" ,\"leadUserName\":\"fred\",\"assigneeType\":\"PROJECT_LEAD\",\"isAssigneeTypeValid\":\"false\",\"project\":\"TEST\"");
input.setContentType("application/json");
postRequest.setEntity(input);
HttpResponse response = httpClient.execute(postRequest);
this is the code i'm implementing.
Output i'm getting is Failed : HTTP error code : 400
Plz help.
we can't tell you. You need to find documentation on the service you are posting to.
The above code is correct, just add the { & } to the JSON string.