cell clicked works locally but not on remote shiny server --DT - ajax
I have an application that listens for a cell click in a DT in any cell and then updates a plot accordingly. The program works perfectly when I runApp() locally. However when I depoloy the app on a shiny server, the click no longer triggers any actions. This discepancy does not exists for other action listeners such as a simple refresh button, as I have demonstrated in the code below. You can see how the discrepancy between remote and local does not exist for the refresh button condition input$refreshButton!=0, but there is a discrepancy using the length(input$table_cell_clicked)>0 trigger condition.
I have done some research into this error and this is what I know so far:
1) I am getting the warning "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience." in the console when the app is deployed remotely. I am told this has something to do with a setting in a file in my shiny server called javascript.min.js and jquery.min.js that says c.async="false" I have searched for every file on my serer with that name or containing the string async="false", and changed the setting to sync="true". However I did not find any files with the exact string c.async="true". I can see the file with this string in the browser console, which gives a location relative to server::port/, but I do not know where that file actually lives on my system, and I suspect it is just a file made on the fly by shiny services.
2) It is possible that this could be fixed with something related to the selectize functionality in some shiny inputs, which may cause the code to execute asynchronously(?). I have tried a few different things but couldn't get any to solve the problem.
3) There is a commonly known annoyance with shiny that it is generally hard to debug. In my case, it would be extremely helpful if I could see the output of the server.R functions as I would when using runApp() locally. Using a call to browser, options(shiny.trace = T) were both recommended, but when I add them to the code below, nothing apprears in the console output. I even tried using sink in order to save to output to some file on the remote server, and it rusn without error, but I do not see any file in the location indicated. If I could at least see the output of this file, or the request/response messages between the server and the client it would go a long way towards debugging this.
So the two questions are: how can I see these messages/output when the app is deployed remotely? And more importantly, how can I implement a fix so that all of my hard work on this project (unfortunately can't disclose any details) will not be a waste.
The basic code for my shiny app is below.
server.R:
server <- function(input, output, session) {
options(shiny.trace = T)
browser()
sink("~/outputfile.txt",append = T,type = "output",split = T)
end_date=as.character(as.Date(Sys.Date()-10))
library(DT)
library(data.table)
library(xtable)
library(zoo)
library(lattice)
library(RSQLite)
output$table = DT::renderDataTable({
thisTable = head(iris)
return(thisTable)
},server = T,options = list(target = 'cell'))
output$plot1 <- renderPlot({
cell= as.numeric(input$table_cell_clicked)
print(cell)
row = as.numeric(input$transtable_row_last_clicked)
print(paste0("last row clicked: ",row))
print(paste0("timestamp: ",Sys.time()))
(cell, file = "/home/plintilhac/cell_file.txt") ## causes error that dumps SND and REC messages to javascript console
# if (length(input$row_last_clicked)>0){ ##works remotely and locally
# if (input$refreshButton!=0){ ##works remotely and locally
if (length(cell)>0){ #works locally, but doesn't work remotely
plot(0,0,xlim = c(-1,1),ylim = c(-1,1))
}
else{return(plot(0,1,xlim = c(-1,1),ylim = c(-1,1)))}}
)
output$text1 <- renderText({
if (input$refreshButton!=0){
"clicked"
}
else{"unclicked"}
})
}
ui.R
shinyUI(
fluidPage(
fluidRow(plotOutput("plot1",click = "plot_click"),theme = "bootstrap.css"),
mainPanel(
DT::dataTableOutput('table'),
fluidRow(
actionButton("refreshButton", "refresh")
)
)
))
EDIT:
I was able to get some output by placing an erroneous line of code right after the cell variable is defined, causing the shiny server to dump output to the javascript console. At this time this is the only way I know how to capture any output. However, the output is quite informative, as it shows that the table_cell_clicked attribute is not being exported on the remote server at all, whereas other attributes such as row_last_clicked are.
here is the output I get when the server is run locally ithout the erroneous line (note it includes table_cell_clicked as a feature):
SEND
{"config":{"workerId":"","sessionId":"ef292cd0c98baee4afa504aa8330b49e"}}
RECV
{"method":"init","data":{"refreshButton:shiny.action":0,".clientdata_output_plot1_width":873,".clientdata_output_plot1_height":400,".clientdata_output_plot1_hidden":false,".clientdata_output_table_hidden":false,".clientdata_pixelratio":1.100000023841858,".clientdata_url_protocol":"http:",".clientdata_url_hostname":"d2rm01",".clientdata_url_port":"8787",".clientdata_url_pathname":"/p/4944/",".clientdata_url_search":"",".clientdata_url_hash_initial":"",".clientdata_singletons":"",".clientdata_allowDataUriScheme":true}}
SEND
{"errors":[],"values":{"table":{"x":{"filter":"none","container":"<table
class=\"display\">\n <thead>\n <tr>\n <th> </th>\n
<th>Sepal.Length</th>\n <th>Sepal.Width</th>\n
<th>Petal.Length</th>\n <th>Petal.Width</th>\n
<th>Species</th>\n </tr>\n
</thead>\n</table>","options":{"target":"cell","selectize":true,"columnDefs":[{"className":"dt-right","targets":[1,2,3,4]},{"orderable":false,"targets":0}],"order":[],"autoWidth":false,"orderClasses":false,"ajax":{"url":"session/ef292cd0c98baee4afa504aa8330b49e/dataobj/table?w=","type":"POST","data":"function(d)
{\nd.search.caseInsensitive = true;\nd.escape = true;\nvar encodeAmp
= function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v)
{encodeAmp(v.search);});\n}"},"serverSide":true,"processing":true},"selection":{"mode":"multiple","selected":null,"target":"row"}},"evals":["options.ajax.data"],"deps":[{"name":"datatables","version":"1.10.7","src":{"file":"/home/plintilhac/R/x86_64-pc-linux-gnu-library/3.2/DT/htmlwidgets/lib/datatables/js","href":"datatables-1.10.7"},"meta":null,"script":"jquery.dataTables.min.js","stylesheet":null,"head":null,"attachment":null},{"name":"datatables-default","version":"1.10.7","src":{"file":"/home/plintilhac/R/x86_64-pc-linux-gnu-library/3.2/DT/htmlwidgets/lib/datatables/css/default","href":"datatables-default-1.10.7"},"meta":null,"script":[],"stylesheet":["dataTables.extra.css","jquery.dataTables.min.css"],"head":null,"attachment":null}]},"plot1":{"src":"data:image/png;[base64
data]","width":873,"height":400,"coordmap":[{"domain":{"left":-1.08,"right":1.08,"bottom":-1.08,"top":1.08},"range":{"left":58.9093125,"right":842.8269375,"bottom":325.745454545455,"top":57.8909090909091},"log":{"x":null,"y":null},"mapping":{}}]}},"inputMessages":[]}
RECV
{"method":"update","data":{"table_rows_selected":[],"table_rows_current":[],"table_rows_all":[],"table_state":null,"table_search":"","table_cell_clicked":{}}}
SEND {"progress":{"type":"binding","message":{"id":"plot1"}}} SEND
{"errors":[],"values":{"plot1":{"src":"data:image/png;[base64
data]","width":873,"height":400,"coordmap":[{"domain":{"left":-1.08,"right":1.08,"bottom":-1.08,"top":1.08},"range":{"left":58.9093125,"right":842.8269375,"bottom":325.745454545455,"top":57.8909090909091},"log":{"x":null,"y":null},"mapping":{}}]}},"inputMessages":[]}
RECV
{"method":"update","data":{"table_rows_current":[1,2,3,4,5,6],"table_rows_all":[1,2,3,4,5,6]}}
RECV {"method":"update","data":{"plot_click":null}} RECV
{"method":"update","data":{"table_cell_clicked":{"row":1,"col":2,"value":3.5},"table_rows_selected":[1],"table_row_last_clicked":1}}
SEND {"progress":{"type":"binding","message":{"id":"plot1"}}} SEND
{"errors":[],"values":{"plot1":{"src":"data:image/png;[base64
data]","width":873,"height":400,"coordmap":[{"domain":{"left":-1.08,"right":1.08,"bottom":-1.08,"top":1.08},"range":{"left":58.9093125,"right":842.8269375,"bottom":325.745454545455,"top":57.8909090909091},"log":{"x":null,"y":null},"mapping":{}}]}},"inputMessages":[]}
RECV {"method":"update","data":{"table_rows_selected":[]}}
while this is the output when it is run remotely with the erroneous line (note table_cell_clicked is not being received):
Loading required package: DBI
SEND {"errors":[],"values":{"table":{"x":{"container":"<table class=\"display\">\n <thead>\n <tr>\n <th> </th>\n <th>Sepal.Length</th>\n <th>Sepal.Width</th>\n <th>Petal.Length</th>\n <th>Petal.Width</th>\n <th>Species</th>\n </tr>\n </thead>\n</table>","options":{"target":"cell","selectize":true,"columnDefs":[{"className":"dt-right","targets":[1,2,3,4]},{"orderable":false,"targets":0}],"order":[],"autoWidth":false,"orderClasses":false,"ajax":{"url":"session/07190712bb533d7cf1929522b19e436a/dataobj/table?w=","type":"POST","data":"function(d) {\nd.search.caseInsensitive = true;\nd.escape = true;\n}"},"serverSide":true,"processing":true},"callback":null,"filter":"none","selection":"multiple"},"evals":["options.ajax.data"],"deps":[{"name":"datatables","version":"1.10.7","src":{"file":"/usr/local/lib/R/site-library/DT/htmlwidgets/lib/datatables/js","href":"datatables-1.10.7"},"meta":null,"script":"jquery.dataTables.min.js","stylesheet":null,"head":null,"attachment":null},{"name":"datatables-default","version":"1.10.7","src":{"file":"/usr/local/lib/R/site-library/DT/htmlwidgets/lib/datatables/css/default","href":"datatables-default-1.10.7"},"meta":null,"script":[],"stylesheet":["dataTables.extra.css","jquery.dataTables.min.css"],"head":null,"attachment":null}]},"plot1":{"src":"data:image/png;[base64 data]","width":1745,"height":400,"coordmap":[{"domain":{"left":-1.08,"right":1.08,"bottom":-1.08,"top":1.08},"range":{"left":58.9062532569046,"right":1714.82850442939,"bottom":325.745454545455,"top":57.8909090909091},"log":{"x":null,"y":null},"mapping":{}}]}},"inputMessages":[]}
RECV {"method":"update","data":{"table_rows_selected":[],"table_rows_current":[],"table_rows_all":[],"table_state":null,"table_search":""}}
RECV {"method":"update","data":{"table_rows_current":["1","2","3","4","5","6"],"table_rows_all":["1","2","3","4","5","6"]}}
RECV {"method":"update","data":{"table_rows_selected":["3"],"table_row_last_clicked":"3"}}
RECV {"method":"update","data":{".clientdata_output_plot1_width":463}}
SEND {"progress":{"type":"binding","message":{"id":"plot1"}}}
SEND {"errors":[],"values":{"plot1":{"src":"data:image/png;[base64 data]","width":463,"height":400,"coordmap":[{"domain":{"left":-1.08,"right":1.08,"bottom":-1.08,"top":1.08},"range":{"left":58.9256188605108,"right":432.81858546169,"bottom":325.745454545455,"top":57.8909090909091},"log":{"x":null,"y":null},"mapping":{}}]}},"inputMessages":[]}
RECV {"method":"update","data":{"plot_click":null}}
SEND {"config":{"workerId":"","sessionId":"7b20c500ee810e198324a75b6512a353"}}
RECV {"method":"init","data":{"refreshButton:shiny.action":0,"ss-net-opt-websocket":true,"ss-net-opt-xdr-streaming":true,"ss-net-opt-xhr-streaming":true,"ss-net-opt-iframe-eventsource":true,"ss-net-opt-iframe-htmlfile":true,"ss-net-opt-xdr-polling":true,"ss-net-opt-xhr-polling":true,"ss-net-opt-iframe-xhr-polling":true,"ss-net-opt-jsonp-polling":true,".clientdata_output_plot1_width":463,".clientdata_output_plot1_height":400,".clientdata_output_plot1_hidden":false,".clientdata_output_table_hidden":false,".clientdata_pixelratio":1.100000023841858,".clientdata_url_protocol":"http:",".clientdata_url_hostname":"d2rm01",".clientdata_url_port":"3838",".clientdata_url_pathname":"/testFunnel/",".clientdata_url_search":"",".clientdata_url_hash_initial":"",".clientdata_singletons":"",".clientdata_allowDataUriScheme":true}}
Error in source(file, ..., keep.source = TRUE, encoding = checkEncoding(file)) :
/srv/shiny-server/testFunnel/server.R:38:10: unexpected ','
37: #print(paste0("timestamp: ",Sys.time()))
38: (cell,
Related
My Roblox Studio script is sometimes having errors.. idk why
So.. I've been coding to make a GUI show the quantity of currency of a player, the datastore API works perfectly but the local script doesn't (it's local because else it would just update it each time a player's currency gets updated and would be a mess being the opposite of what I want to) and well... sometimes it loads the currency into the GUI but other times it just stays on the original text: "Label" instead of my current currency (4600) here's the proof What normally happens and should always happen What sometimes happens and shouldn't happen: here's the script, I've tried putting waits on the start but the original code is inside the while true do.. wait(game.Players.LocalPlayer:WaitForChild("Data") wait(game.Players.LocalPlayer.Data:WaitForChild("Bells")) while true do script.Parent.TextLabel.Text = game.Players.LocalPlayer:WaitForChild("Data"):WaitForChild("Bells").Value wait() --wait is for not making the loop break and stop the whole script end well.. if you want to see if data is really in the player, here's the script, it requires a API (DataStore2) --[Animal Crossing Roblox Edition Data Store]-- --Bryan99354-- --Module not mine-- --Made with a AlvinBlox tutorial-- --·.·.*[Get Data Store, do not erase]*.·.·-- local DataStore2 = require(1936396537) --[Default Values]-- local DefaultValue_Bells = 300 local DefaultValue_CustomClothes = 0 --[Data Store Functions]-- game.Players.PlayerAdded:Connect(function(player) --[Data stores]-- local BellsDataStore = DataStore2("Bells",player) local Data = Instance.new("Folder",player) Data.Name = "Data" Bells = Instance.new("IntValue",Data) Bells.Name = "Bells" local CustomClothesDataStore = DataStore2("CustomClothes",player) local CustomClothes = Instance.new("IntValue",Data) CustomClothes.Name = "CustomClothes" local function CustomClothesUpdate(UpdatedValue) CustomClothes.Value = CustomClothesDataStore:Get(UpdatedValue) end local function BellsUpdate(UpdatedValue) Bells.Value = BellsDataStore:Get(UpdatedValue) end BellsUpdate(DefaultValue_Bells) CustomClothesUpdate(DefaultValue_CustomClothes) BellsDataStore:OnUpdate(BellsUpdate) CustomClothesDataStore:OnUpdate(CustomClothesUpdate) end) --[test and reference functions]-- workspace.TestDevPointGiver.ClickDetector.MouseClick:Connect(function(player) local BellsDataStore = DataStore2("Bells",player) BellsDataStore:Increment(50,DefaultValue_Bells) end) workspace.TestDevCustomClothesGiver.ClickDetector.MouseClick:Connect(function(player) local CustomClothesDataStore = DataStore2("CustomClothes",player) CustomClothesDataStore:Increment(50,DefaultValue_CustomClothes) end) the code that creates "Data" and "Bells" is located in the comment: Data Stores the only script that gets the issue is the short one with no reason :< I hope that you can help me :3 #Night94 I tryed your script but it also failed sometimes
The syntax in your LocalScript is a little off with the waits. With that fixed, it works every time. Also, I would use an event handler instead of updating the value with a loop: game.Players.LocalPlayer:WaitForChild("Data"):WaitForChild("Bells").Changed:Connect(function(value) script.Parent.TextLabel.Text = value end)
Code is not delievered by SendCodeRequest without error and this happens only on server-side with Heroku
Here is my situation: the same Telethon code is used on my local machine and on the server. Requesting authorization code from local machine works fine. Requesting the code from the server does not produce any error, and code is not sent. Sometimes it works even from the server without any changes in code. I suppose there might be some ip blocks or something related to the ip, cause that is the only thing which might differ on the server side: Heroku assign ip addresses dynamically, so, there might by some subnets which are blocked by Telegram API for some reason. But there is no error and that is really strange. There are too many ip addresses to disprove the hypothesis. I need to catch at least one ip address which gives me opposite results: one time code it recieved and another time does not. So I am stuck with this situation and have no ideas how it could be fixed or clarified. global t t = None async def ssssendCode(phone): global t try: if os.path.isfile(phone+'.session'): logger.debug('client file exists') else: logger.debug('client file does not exist') if t is None: t = TelegramClient(phone, settings['telegramClientAPIId'], settings['telegramClientAPIHash']) t.phone = phone #t.phone_code_hash = None await t.connect() #response = await t.send_code_request(phone=phone,force_sms=True) s3_session.resource('s3').Bucket('telethon').upload_file(str(phone)+".session", str(phone)+".session") logger.debug(str(requests.get('https://httpbin.org/ip').text)) response = await t.send_code_request(phone=phone) logger.debug(str(t.is_connected())) except Exception as e: response = str(e) return str(response) example of response to the local machine request SentCode(type=SentCodeTypeSms(length=5), phone_code_hash='b5b069a2a4122040f1', next_type=CodeTypeCall(), timeout=120) example of reponse to the server-side request SentCode(type=SentCodeTypeSms(length=5), phone_code_hash='0e89db0324c1af0149', next_type=CodeTypeCall(), timeout=120) send_code_request is the from the Telethon without modifications async def send_code_request( self: 'TelegramClient', phone: str, *, force_sms: bool = False) -> 'types.auth.SentCode': """ Sends the Telegram code needed to login to the given phone number. Arguments phone (`str` | `int`): The phone to which the code will be sent. force_sms (`bool`, optional): Whether to force sending as SMS. Returns An instance of :tl:`SentCode`. Example .. code-block:: python phone = '+34 123 123 123' sent = await client.send_code_request(phone) print(sent) """ result = None phone = utils.parse_phone(phone) or self._phone phone_hash = self._phone_code_hash.get(phone) if not phone_hash: try: result = await self(functions.auth.SendCodeRequest( phone, self.api_id, self.api_hash, types.CodeSettings())) except errors.AuthRestartError: return await self.send_code_request(phone, force_sms=force_sms) # If we already sent a SMS, do not resend the code (hash may be empty) if isinstance(result.type, types.auth.SentCodeTypeSms): force_sms = False # phone_code_hash may be empty, if it is, do not save it (#1283) if result.phone_code_hash: self._phone_code_hash[phone] = phone_hash = result.phone_code_hash else: force_sms = True self._phone = phone if force_sms: result = await self( functions.auth.ResendCodeRequest(phone, phone_hash)) self._phone_code_hash[phone] = result.phone_code_hash return result Just in case: I have much more than 2 minutes between attempts to get a code from the local machine and server, so it is absolutely not the timeout issue. And moreover: even when requesting the code from the local right after half a minute from the failed server-side attemp: code is coming almost immediately.
Pushing data to websocket browser client in Lua
I want to use a NodeMCU device (Lua based top level) to act as a websocket server to 1 or more browser clients. Luckily, there is code to do this here: NodeMCU Websocket Server (courtesy of #creationix and/or #moononournation) This works as described and I am able to send a message from the client to the NodeMCU server, which then responds based on the received message. Great. My questions are: How can I send messages to the client without it having to be sent as a response to a client request (standalone sending of data)? When I try to call socket.send() socket is not found as a variable, which I understand, but cannot work out how to do it! :( Why does the decode() function output the extra variable? What is this for? I'm assuming it will be for packet overflow, but I can never seem to make it return anything, regardless of my message length. In the listen method, why has the author added a queuing system? is this essential or for applications that perhaps may receive multiple simultaneous messages? Ideally, I'd like to remove it. I have simplified the code as below: (excluding the decode() and encode() functions - please see the link above for the full script) net.createServer(net.TCP):listen(80, function(conn) local buffer = false local socket = {} local queue = {} local waiting = false local function onSend() if queue[1] then local data = table.remove(queue, 1) return conn:send(data, onSend) end waiting = false end function socket.send(...) local data = encode(...) if not waiting then waiting = true conn:send(data, onSend) else queue[#queue + 1] = data end end conn:on("receive", function(_, chunk) if buffer then buffer = buffer .. chunk while true do local extra, payload, opcode = decode(buffer) if opcode==8 then print("Websocket client disconnected") end --print(type(extra), payload, opcode) if not extra then return end buffer = extra socket.onmessage(payload, opcode) end end local _, e, method = string.find(chunk, "([A-Z]+) /[^\r]* HTTP/%d%.%d\r\n") local key, name, value for name, value in string.gmatch(chunk, "([^ ]+): *([^\r]+)\r\n") do if string.lower(name) == "sec-websocket-key" then key = value break end end if method == "GET" and key then acceptkey=crypto.toBase64(crypto.hash("sha1", key.."258EAFA5-E914-47DA-95CA-C5AB0DC85B11")) conn:send( "HTTP/1.1 101 Switching Protocols\r\n".. "Upgrade: websocket\r\nConnection: Upgrade\r\n".. "Sec-WebSocket-Accept: "..acceptkey.."\r\n\r\n", function () print("New websocket client connected") function socket.onmessage(payload,opcode) socket.send("GOT YOUR DATA", 1) print("PAYLOAD = "..payload) --print("OPCODE = "..opcode) end end) buffer = "" else conn:send( "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World!", conn.close) end end) end)
I can only answer 1 question, the others may be better suited for the library author. Besides, SO is a format where you ask 1 question normally. How can I send messages to the client without it having to be sent as a response to a client request (standalone sending of data)? You can't. Without the client contacting the server first and establishing a socket connection the server wouldn't know where to send the messages to. Even with SSE (server-sent events) it's the client that first initiates a connection to the server.
SNMPv3 not in time window
I try to query a Cisco SMB (small business switch) to read its hostname. My code returns "not in time window (1.3.6.1.6.3.15.1.1.2.0). Net-Snmp works fine. The difference I found using wireshark is that net-snmp sets msgAuthorativeEngineTime after it receives not in time window error. Discovery discovery = Messenger.GetNextDiscovery(SnmpType.GetRequestPdu); ReportMessage report = discovery.GetResponse(60000, new IPEndPoint(IPAddress.Parse("10.105.9.10"), 161)); OctetString username = new OctetString("test"); var auth = new SHA1AuthenticationProvider(new OctetString("Testtest123!")); var priv = new DESPrivacyProvider(new OctetString("Testtest123!"), auth); // read switch hostname GetRequestMessage request = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, username, new List<Variable> { new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.5.0")) }, priv, Messenger.MaxMessageSize, report); ISnmpMessage reply = request.GetResponse(60000, router); (not in time window) Please find a wireshark screenshot of sharp-snmp: And net-snmp: Thank you for your help!
According to the snmpget sample (updated link here), you have to call two times the GetRequestMessage method. Be aware that the code uses the report variable in the first call, then the reply one in the latter, otherwise it will not work (= not in time window message) (I lost half a day to get this!)
Sending An HTTP Request using Intersystems Cache
I have the following Business Process defined within a Production on an Intersystems Cache Installation /// Makes a call to Merlin based on the message sent to it from the pre-processor Class sgh.Process.MerlinProcessor Extends Ens.BusinessProcess [ ClassType = persistent, ProcedureBlock ] { Property WorkingDirectory As %String; Property WebServer As %String; Property CacheServer As %String; Property Port As %String; Property Location As %String; Parameter SETTINGS = "WorkingDirectory,WebServer,Location,Port,CacheServer"; Method OnRequest(pRequest As sgh.Message.MerlinTransmissionRequest, Output pResponse As Ens.Response) As %Status { Set tSC=$$$OK Do ##class(sgh.Utils.Debug).LogDebugMsg("Packaging an HTTP request for Saved form "_pRequest.DateTimeSaved) Set dateTimeSaved = pRequest.DateTimeSaved Set patientId = pRequest.PatientId Set latestDateTimeSaved = pRequest.LatestDateTimeSaved Set formName = pRequest.FormName Set formId = pRequest.FormId Set episodeNumber = pRequest.EpisodeNumber Set sentElectronically = pRequest.SentElectronically Set styleSheet = pRequest.PrintName Do ##class(sgh.Utils.Debug).LogDebugMsg("Creating HTTP Request Class") set HTTPReq = ##class(%Net.HttpRequest).%New() Set HTTPReq.Server = ..WebServer Set HTTPReq.Port = ..Port do HTTPReq.InsertParam("DateTimeSaved",dateTimeSaved) do HTTPReq.InsertParam("HospitalNumber",patientId) do HTTPReq.InsertParam("Episode",episodeNumber) do HTTPReq.InsertParam("Stylesheet",styleSheet) do HTTPReq.InsertParam("Server",..CacheServer) Set Status = HTTPReq.Post(..Location,0) Quit:$$$ISERR(tSC) Do ##class(sgh.Utils.Debug).LogDebugMsg("Sent the following request: "_Status) Quit tSC } } The thing is when I check the debug value (which is defined as a global) all I get is the number '1' - I have no idea therefore if the request has succeeded or even what is wrong (if it has not) What do I need to do to find out A) What is the actual web call being made? B) What the response is?
There is a really slick way to get the answer the two questions you've asked, regardless of where you're using the code. Check the documentation out on the %Net.HttpRequest object here: http://docs.intersystems.com/ens20102/csp/docbook/DocBook.UI.Page.cls?KEY=GNET_http and the class reference here: http://docs.intersystems.com/ens20102/csp/documatic/%25CSP.Documatic.cls?APP=1&LIBRARY=ENSLIB&CLASSNAME=%25Net.HttpRequest The class reference for the Post method has a parameter called test, that will do what you're looking for. Here's the excerpt: method Post(location As %String = "", test As %Integer = 0, reset As %Boolean = 1) as %Status Issue the Http 'post' request, this is used to send data to the web server such as the results of a form, or upload a file. If this completes correctly the response to this request will be in the HttpResponse. The location is the url to request, e.g. '/test.html'. This can contain parameters which are assumed to be already URL escaped, e.g. '/test.html?PARAM=%25VALUE' sets PARAM to %VALUE. If test is 1 then instead of connecting to a remote machine it will just output what it would have send to the web server to the current device, if test is 2 then it will output the response to the current device after the Post. This can be used to check that it will send what you are expecting. This calls Reset automatically after reading the response, except in test=1 mode or if reset=0. I recommend moving this code to a test routine to view the output properly in terminal. It would look something like this: // To view the REQUEST you are sending Set sc = request.Post("/someserver/servlet/webmethod",1) // To view the RESPONSE you are receiving Set sc = request.Post("/someserver/servlet/webmethod",2) // You could also do something like this to parse your RESPONSE stream Write request.HttpResponse.Data.Read()
I believe the answer you want to A) is in the Server and Location properties of your %Net.HttpRequest object (e.g., HTTPReq.Server and HTTPReq.Location). For B), the response information should be in the %Net.HttpResponse object stored in the HttpResponse property (e.g. HTTPReq.HttpResponse) after your call is completed. I hope this helps! -Derek (edited for formatting)
From that code sample it looks like you're using Ensemble, not straight-up Cache. In that case you should be doing this HTTP call in a Business Operation that uses the HTTP Outbound Adapter, not in your Business Process. See this link for more info on HTTP Adapters: http://docs.intersystems.com/ens20102/csp/docbook/DocBook.UI.Page.cls?KEY=EHTP You should also look into how to use the Ensemble Message Browser. That should help with your logging needs.