Attempting to extract the field "searched_count" in Udemy's API, but I'm not sure about the syntax.
If anyone can point me in the right direction, it will be highly appreciated. I'm using Sinatra and parsing the api request using net/http.
require 'sinatra'
require 'net/http'
require 'json'
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
def get_search_count(term)
url = 'https://www.udemy.com/api-2.0/search-suggestions?q=java'
uri = URI(url)
response = Net::HTTP.get(uri)
JSON.parse(response)
return response ["results"][0]["searched_count"]
end
get '/' do
return get_search_count("java")
end
I'm attempting to display the number on the web page. I don't receive any errors while I'm running it, but I can't tell if I'm actually receiving feedback from the request.
If it helps, here's a snippet from the json file:
{
"results": [
{
"_class": "search_log",
"id": 88,
"phrase": "java",
"searched_count": 3749730,
"url": "/courses/search/?q=java"
},
Edit: Here's my attempt at showing it on the web page. Located in index.erb
<html>
<head>
<title><%= #title %></title>
</head>
<body>
<h1><%= #headline %></h1>
<p><%= #paragraph %></p>
<form action="/action_page.php" method="get">
Search Term: <input type="text" name="term"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Also, my updated code in web.rb :
require 'sinatra'
require 'net/http'
require 'json'
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
def get_search_count(term)
url = 'https://www.udemy.com/api-2.0/search-suggestions?q=java'
uri = URI(url)
response = Net::HTTP.get(uri)
parsed_response = JSON.parse(response)
return parsed_response ["results"][0]["searched_count"]
end
get '/' do
return get_search_count("java")
end
get '/term' do
erb :index
end
get '/action_page.php' do
return get_search_count(params[:name])
end
Please change the method to something like this
def get_search_count(term)
url = 'https://www.udemy.com/api-2.0/search-suggestions?q=java'
uri = URI(url)
response = Net::HTTP.get(uri)
parsed_response = JSON.parse(response)
return parsed_response ["results"][0]["searched_count"]
end
NB:If you are getting the response properly it will work.
Related
I have this a custom action in Task controller, which has if else
statements and returns Api calls from Safe browsing api, which I need to render to users
in index.html.erb without refreshing the page. I've tried Ajax but it doesn't seem to
work correctly.In addition, I've tried to search and follow some Hotwire and Turbo
tutorials but they seem to solve complicated problems unlike my problem.
My problem and solution are simple, a user submits link to the server to be checked by
Google Safe Browsing API and return results back to the user rendered in the same
page without refreshing. I currently have them rendered in a different page by using
for example
render plain: "" and return
Finally, this's my code and I need a simple solution to render the custom action results
to users without refreshing the page.
This's check_url action in tasks_controller.rb
def check_url
#id = params[:id]
#result = params[:result]
if params[:link].present?
api_key = ENV[""]
# Set up the request parameters
url = params[:link]
formatted_url = canonicalize_url(url)
threat_types = ["MALWARE", "THREAT_TYPE_UNSPECIFIED", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE", "POTENTIALLY_HARMFUL_APPLICATION"]
platform_types = ["ANY_PLATFORM"]
body = {
client: {
clientId: api_key,
clientVersion: "1.0.0",
},
threatInfo: {
threatTypes: threat_types,
platformTypes: platform_types,
threatEntryTypes: %w[URL THREAT_ENTRY_TYPE_UNSPECIFIED EXECUTABLE],
threatEntries: [
{ url: formatted_url },
],
},
}
# Set up the request headers
headers = {
"Content-Type" => "application/json",
}
# Make the request to the Safe Browsing API
response = HTTP.post(
"https://safebrowsing.googleapis.com/v4/threatMatches:find?key=",
json: body,
headers: headers,
)
# Check the response
if response.code == 200
data = JSON.parse(response.body)
puts JSON.pretty_generate(data)
#result = response.body
if data["matches"].try(:empty?)
render plain: "The URL is safe" and return
else
render plain: "The URL is not safe" and return
end
else
render plain: "An error occurred"
end
else
puts "link variable is empty"
end
puts "Response code: #{response.code}"
puts "Response body: #{response.body}"
puts "Request parameters: #{body}"
puts "Request headers: #{headers}"
end
private
def task_params
params.require(:task).permit(:link, :result)
end
end
This's the submission form in _form.html.erb
<%= form_tag("/check_url", method: "post") do %>
<%= label_tag(:link, "Enter a link:") %>
<%= text_field_tag(:link) %>
<%= submit_tag("Submit") %>
<% end %>
This's index.html.erb
<% if notice.present? %>
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice">
<%= notice %>
</p>
<% end %>
<h1 class="font-bold text-2xl">Task Manager</h1>
<div class="mt-4">
<%= render "form", task: #task %>
<%= render 'tasks/check_url' %>
</div>
Thank you all and please ask any questions or requests, I'm new to Ruby on
Rails and want to grasp it.
In view:
response = JsonResponse(available_lessons, safe=False)
In template:
var available_lessons_json = {{available_lessons_json.content|safe}}
In my source js file I see:
var available_lessons_json = b'{"courses": {"courseName": "Everyday English", "lessons": ["Phrasal Verbs I", "Phrasal Verbs II", "Phrasal Verbs III"]}}'
which is giving me the error "Uncaught SyntaxError: Unexpected string"
If you want to render your template with your data, your should use render function not JsonResponse. This should be like this.
return render(request, template, {'available_lessons': available_lessons})
In your template
var available_lessons_json = {{available_lessons|safe}}
Javascript doesn't like the b at the start of your response content, which denotes that it is a byte string. response.content always encodes to bytes- which you can decode with {{available_lessons_json.content.decode|safe}}
Just be aware that if response.content contains user input you're likely to be introducing XSS vulnerabilities into your site
I would like to access to a website with a lot of information and display all of it (as of now). However, I want to use JSON.parse and also authenticate the user and password in order to extract that information.
This is what I have:
require 'net/http'
require 'json'
url = 'http://robotrevolution.net/interface/int_order_options.php'
uri = URI(url)
response = Net::HTTP.get(uri)
jsonVal = JSON.parse(open(response))
puts jsonVal
However, while looking up online, I found I can use this:
require 'net/http'
require 'json'
require 'uri'
uri = URI('http://robotrevolution.net/interface/int_order_options.php')
Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https',
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |http|
request = Net::HTTP::Get.new uri.request_uri
request.basic_auth 'username', 'password'
response = http.request request # Net::HTTPResponse object
puts response
puts response.body
end
Moreover, I would like to find a way to mix both of them and use automatic authentication as well as parse JSON at the same time. Thank you.
Consider using RestClient library (https://github.com/rest-client/rest-client).
Example:
require 'rest-client'
require 'json'
require 'ostruct'
url_endpoint = 'https://api.example.com'
basic_auth_user = 'user'
basic_auth_password = 'pass'
basic_auth_creds = "#{basic_auth_user}:#{basic_auth_password}"
response = RestClient.get(url_endpoint, {
Authorization: "Basic #{Base64::encode64(basic_auth_creds)}"
})
json = JSON.parse(response.body, object_class: OpenStruct) unless response.empty?
I have been looking all over for how to properly check respond to a application/json type as well as a submitted form. I finally got it working on my own with the following code. Can someone explain why it works? Or offer advice on a better solution to achieve the same thing?
post '/login', provides: :json do
p = params
if request.content_type == 'application/json'
params = JSON.parse(request.body.read, :symbolize_names => true)
else
params = p
end
requires(params, :email, :password)
if #user = User.find_by_email(params[:email])
if #user.authenticate(params[:password])
log_user_in(#user)
rabl :login, object: #user
else
error 404, {error: "incorrect credentials"}.to_json
end
else
error 404, {error: "user not found"}.to_json
end
end
JSON requests are submitted in the body of the html request so this works but overriding the params hash is not advisable if using RESTful routes.
Hey Curtis.
Just use ::Rack::JSONBodyParser from rack-contrib:
A Rack middleware that makes JSON-encoded request bodies available in
the request.params hash. By default it parses POST, PATCH, and PUT
requests whose media type is application/json. You can
configure it to match any verb or media type via the :verbs
and :media options.
Examples:
Parse POST and GET requests only
use Rack::JSONBodyParser, verbs: ['POST', 'GET']
Parse POST|PATCH|PUT requests whose Content-Type matches 'json'
use Rack::JSONBodyParser, media: /json/
Parse POST requests whose Content-Type is 'application/json' or 'application/vnd+json'
use Rack::JSONBodyParser, verbs: ['POST'], media: ['application/json', 'application/vnd.api+json']
I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below
private_resource = RestClient::Resource.new( 'https://mysite.com')
params = {:user => {:email => 'user#mysite.com', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})
There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client
I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here
Put the below code into your application controller :
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
And call this method using before_filter .
For more details check :
http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html
And check this issue in rails : https://github.com/rails/rails/issues/3041
In your app/views/products/new.json.jbuilder, add this:
json.authenticity_token form_authenticity_token
This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.