Trouble executing server-side cgi code from javascript or JQuery - javascript

I am trying to send a message from the webclient via JavaScript or JQuery to the Apache2 webserver on Debian Jessie, to execute a compiled C program that sends a POSIX message_queue, but I cannot get it to work.
I have the following files in my cgi directory:
root#asus:/var/www/cgi-bin# ls -l
-rwxr-xr-x 1 www-data www-data 59008 Mar 20 17:47 mq_client.cgi
-rwxr-xr-x 1 www-data www-data 115 Mar 17 18:14 test.pl
mq_client.cgi is a C-compiled executable that generates the POSIX message. If I execute
lachlan#asus:~$ /var/www/cgi-bin/mq_client.cgi
the correct message is sent and received by the server.
Test.pl is a perl scrpt that generates html code and if I execute
lachlan#asus:~$ /var/www/cgi-bin/test.pl
this works fine also and gives the output:
Content-type: text/html
Just testing.
If I use the chromium webserver as follows:
http://localhost/cgi-bin/test.pl
I get the correct result: 'Just Testing'
However, I have not been able to get the mq_client.cgi code to execute from the webserver. I have searched many website and tried many options as indicated below.
This is my code of “index.html” (Note the errors only occur when I press the button)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/jq_182.js"></script>
<script type="text/javascript">
function mapToggle(){
// different options as indicated below
}
</script>
</head>
<body>
<div id = "label"> </div>
<form action = "" class = "mapButton">
<p> <button type= "button" onclick = "mapToggle()" class = "button2property"> Map Toggle </button> </p>
</form>
</body>
</html>
The different options I have tried (one by one) in the location indicated above are:
// option 1.
var site = 22;
$.ajax({type: "PUT", url: "/cgi-bin/mq_client.cgi", async: false, data: site});
This gives the following 2 errors in Chromium:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
jq_182.js:2
PUT http://localhost/cgi-bin/mq_client.cgi 500 (Internal Server Error)
// option 2.
var site = 22;
$.ajax({type: "GET", url: "/cgi-bin/mq_client.cgi", async: false, data: site});
This gives the following 2 errors:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
jq_182.js:2
GET http://localhost/cgi-bin/mq_client.cgi 500 (Internal Server Error)
// option 3.
var myRequest = new XMLHttpRequest();
myRequest.open("GET", "/cgi-bin/mq_client.cgi");
myRequest.send();
This gives the following error code:
index2.html:21 GET http://localhost/cgi-bin/mq_client.cgi 500 (Internal Server Error)
//option 4.
src = "/cgi-bin/mq_client.cgi";
No errors are indicated in Chromium, but there is also no message sent
// option 5.
var img = new Image();
img.src = "/cgi-bin/mq_client.cgi";
Resulting error: GET http://localhost/cgi-bin/mq_client.cgi 500 (Internal Server Error)
// option 6. Also changed the filename to index.shtml
<!--#exec cmd="/cgi-bin/mq_client.cgi" -->
No errors are indicated in Chromium, but there are no messages sent
// Option 7.
var client = new XMLHttpRequest();
client.open("post", "/cgi-bin/mq_client.cgi", true);
No errors are indicated in Chromium, but there are no messages sent.
// Option 8.
var client = new XMLHttpRequest();
var formx = new FormData();
formx.append("dummy","data");
client.open("post", "/cgi-bin/mq_client.cgi", true);
client.setRequestHeader("Content-Type", "multipart/form-data");
client.send(formx);
Error: index2.html:45 POST http://localhost/cgi-bin/mq_client.cgi 500 (Internal Server Error)
I have reviewed many references and tried their suggestions, but have not yet solved the problem.
Any ideas on where to look for the problem would be appreciated.
Lachlan
The Server side code generates a POSIX Message queue:
The server code sends out a POSIX message to a server. The code is as follows:
int main(void) {
char msg[5];
// Open queue already created
mqd_t mQueue = mq_open("q1", O_WRONLY, NULL);
if (mQueue == (mqd_t) -1){
puts("Queue Open Failed\n");
return EXIT_FAILURE;
}
puts("Queue Opened\n");
// Send Message
msg[0] = 22;
if ( mq_send(mQueue, msg, 5, 1) == -1){
puts("Queue Send Failure\n");
return EXIT_FAILURE;
}
puts("Message Sent\n");
mq_close(mQueue);
return EXIT_SUCCESS;
}
Here is the Server code to receive the message queue:
int main(void) {
char msg[MAX_MSG_SIZE];
unsigned int prio;
ssize_t msgLength = 0;
// Create queue
struct mq_attr attr;
attr.mq_maxmsg = 4;
attr.mq_msgsize = 5;
mQueue = mq_open(“q1”, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO, &attr);
if (mQueue == (mqd_t) -1){
puts("Queue Create Failed\n");
return EXIT_FAILURE;
}
puts("Queue Created\n");
// get message - This blocks
msgLength = mq_receive(mQueue, msg, MAX_MSG_SIZE, &prio);
if (msgLength == -1){
puts("Queue Read Failure\n");
return EXIT_FAILURE;
}
printf("Message Received: %i\n", (int)msg[0]);
mq_close(mQueue);
return EXIT_SUCCESS;
}
The permissions to access the server queue are:
S_IRWXU | S_IRWXG | S_IRWXO
The permissions for executing the cgi code are:
-rwxr-xr-x 1 www-data www-data 59008 Mar 20 17:47 mq_client.cgi
If this is a permission problem can you suggest which permissions are missing?

I finally found another post that helped solve the problem. Yes it was a permissions problem. The program permissions were overriding the message queue permissions. Once this was addressed the problem was solved.
Regards
Lachlan

Related

Can't remove CORS error even so I included all headers

I am writing simple web-site with js-client and a server side(python) I did everything to remove CORS error but nothing works. I wrote all needed headers for this but still get this error. So web-site should send a request to a server and get answer.
Error:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
myFile.html:
<!DOCTYPE html>
<html>
<head>
<title>requestJs</title>
</head>
<body>
<button class="myButton">SEND</button>
<script type="text/javascript">
let theButton = document.querySelector(".myButton");
theButton.addEventListener('click',function() {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
alert(`Статус: ${xhr.status}; Результат: ${xhr.response}`)
};
xhr.onerror = function() {
alert('Ошибка запроса');
};
xhr.open("GET", "http://127.0.0.1:8000/", true);
xhr.send(2);
})
</script>
</body>
</html>
Server side:
import http.server as httpserver
class CORSHTTPRequestHandler(httpserver.SimpleHTTPRequestHandler):
def send_head(self):
"""Common code for GET and HEAD commands.
This sends the response code and MIME headers.
Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do.
"""
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.html":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
# Always read in binary mode. Opening files in text mode may cause
# newline translations, making the actual size of the content
# transmitted *less* than the content-length!
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs[6]))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.send_header("Access-Control-Allow-Origin:", "*")
self.send_header("Access-Control-Allow-Methods:", "GET,HEAD,PUT,PATCH,POST,DELETE")
self.send_header("Access-Control-Allow-Headers:", "Content-Type, Access-Control-Allow-Origin, xxx")
self.end_headers()
return f
if __name__ == "__main__":
import os
import socketserver
import sys
PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8000
handler = CORSHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), handler)
print(f"serving at port {PORT}")
httpd.serve_forever()
Help me please, what is my problem?
This is not a comprehensive answer but it might help.
CORS is entirely a browser feature. You can turn it off in your browser. I suggest the first step therefore is to launch a CORS-free browser to test your app. Make sure not to open your banking page in this browser session though, it isn't safe!
google-chrome --user-data-dir=/var/tmp/Chrome --disable-web-security
If everything works then then issue is just CORS.
If you are only running in a dev environment, you can just do this everytime even.
If you are running in production, the easiest option is often just to use a gateway that fixes this stuff for you. That's how I got mine working.
If the above isn't good enough and you want to debug, remember that all browser CORS requests are initiated by a preflight OPTIONS requests. Sometimes that's where the problem comes in. Make sure your server is able to handle and respond to OPTIONS, and check that it is responding correctly.

Server Sent Events in Golang - Browser only get event stream on localhost

I try Server Sent Events with golang. I use the library described here: https://thoughtbot.com/blog/writing-a-server-sent-events-server-in-go
I got it working but only with localhost but if I use my hostname in the address line of my browser it doesnt work. It also doesn't work if I call the website on another client.
I tried something to solve it. If I send some SSE to the client and kill the server application then all sent events arrive the browser application at once.
If I use curl it works:
curl -v myhost:8081/updates
* Trying ....
* TCP_NODELAY set
* Connected to myhost (...) port 8081 (#0)
> GET /updates HTTP/1.1
> Host: myhost:8081
> User-Agent: curl/7.50.3
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Cache-Control: no-cache
< Connection: keep-alive
< Content-Type: text/event-stream
< Date: Fri, 29 Nov 2019 17:07:27 GMT
< Transfer-Encoding: chunked
<
data: {"X":127,"Y":227,"Zeitpunkt":"29.11.2019 18:07:27"}
data: {"X":128,"Y":228,"Zeitpunkt":"29.11.2019 18:07:28"}
data: {"X":128,"Y":228,"Zeitpunkt":"29.11.2019 18:07:29"}
What could be the problem? I use the newest golang library
Here is my javascript code:
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("updates");
source.onmessage = function(event) {
var pmstat = jQuery.parseJSON(event.data);
$('#bestandX').html(pmstat.X);
$('#bestandY').html(pmstat.Y);
$('#aktualisiertAm').html(pmstat.Zeitpunkt);
};
} else {
$('body').html('<h1 style="color: red">Browser unterstützt keine Server-sent events.</h1>')
}
</script>
and here is the golang code I use from the library:
// Implement the http.Handler interface.
// This allows us to wrap HTTP handlers (see auth_handler.go)
// http://golang.org/pkg/net/http/#Handler
func (broker *Broker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// Make sure that the writer supports flushing.
//
flusher, ok := rw.(http.Flusher)
if !ok {
http.Error(rw, "Streaming unsupported!", http.StatusInternalServerError)
return
}
// Set the headers related to event streaming.
rw.Header().Set("Content-Type", "text/event-stream")
rw.Header().Set("Cache-Control", "no-cache")
rw.Header().Set("Connection", "keep-alive")
rw.Header().Set("Access-Control-Allow-Origin", "*")
// Each connection registers its own message channel with the Broker's connections registry
messageChan := make(MessageChan)
// Signal the broker that we have a new connection
broker.newClients <- messageChan
// Remove this client from the map of connected clients
// when this handler exits.
defer func() {
fmt.Println("HERE.")
broker.closingClients <- messageChan
}()
// "raw" query string option
// If provided, send raw JSON lines instead of SSE-compliant strings.
req.ParseForm()
raw := len(req.Form["raw"]) > 0
// Listen to connection close and un-register messageChan
notify := rw.(http.CloseNotifier).CloseNotify()
go func() {
<-notify
broker.closingClients <- messageChan
}()
// block waiting or messages broadcast on this connection's messageChan
for {
// Write to the ResponseWriter
if raw {
// Raw JSON events, one per line
fmt.Fprintf(rw, "%s\n", <-messageChan)
} else {
// Server Sent Events compatible
fmt.Fprintf(rw, "data: %s\n\n", <-messageChan)
}
// Flush the data inmediatly instead of buffering it for later.
flusher.Flush()
}
}
I tried this library and the same happens here:
https://github.com/alexandrevicenzi/go-sse
Now I tried to close the connection after every message and give the browser the command to reconnect immediately. Here are the two lines I added in the code:
...
go func() {
<-notify
broker.closingClients <- messageChan
}()
// block waiting or messages broadcast on this connection's messageChan
for {
// Write to the ResponseWriter
if raw {
// Raw JSON events, one per line
fmt.Fprintf(rw, "%s\n", <-messageChan)
} else {
// Server Sent Events compatible
fmt.Fprintf(rw, "retry: %d\n", 0) //<--- I added this
fmt.Fprintf(rw, "data: %s\n\n", <-messageChan)
}
// Flush the data inmediatly instead of buffering it for later.
flusher.Flush()
break //<--- I added this
}
}
Now it almost works but this is only a workaround for me. Does someone have a good solution how it works while keeping the connection alive?

Requests to python API stalled by chrome for 10 seconds for no reason. [BaseHTTPServer + Chrome]

Overview of the problem
I am running a webpage and an API written in python. The webpage sends some data to the python API in a POST request, which processes it and sends it back. The API works fine with curl requests and console AJAX requests. However, when I load the webpage in a new tab, all POST requests for the first 10 seconds or so are ‘stalled’ (not carried out by Chrome) until they fail. After around 10 seconds POST requests work fine, and the python API catches a broken pipe (ERRNO 32, logs below). If I hard refresh the tab, then the site immediately works and the request isn’t stalled at all, however if I open a new tab with the site in then again there’s this 10 second delay.
Specifics
This only happens on Chrome, it works fine on Firefox and Safari. I have run the API and the webpage on both localhost and an AWS instance, and there is still the ~10 second delay, after which it works fine. It happens on chrome on other computers and works on Firefox on other computers.
How I've tried to fix it
Chrome apparently stalls requests when its either negotiating a proxy connection or reaches its limit of 6 TCP connections. I don’t know why doing a hard-reset wouldn’t cause it to have to re-negotiate its connection to the API, or why it wouldn’t have to do that each time. Even if it is doing that, its shouldn’t consistently take around ~10 seconds should it? I’ve also ensured that the site is not reaching 6 TCP connections.
Potential problem?
I have no problems with the HTTP request stalling if I change the request to be from another site, and this issue is specific to Chrome, so I’m wondering if Chrome implements XMLHTTPRequests in a way that BaseHTTPRequests doesn’t know how to deal with, and that’s leading to the broken pipe. But I don’t know why it always fixes itself after ~10 seconds each time.
I’ve spent many hours on this now, any help would be massively appreciated please!
HTML/JS:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>OSR Web</title>
</head>
<body>
<script>
var http = new XMLHttpRequest();
var url = "http://localhost:1234";
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
var bestGuess = http.responseText;
console.log(bestGuess);
}
}
document.addEventListener("click", function(event){
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send("TestData");
});
</script>
</body>
</html>
Python API:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class S(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
def do_GET(self):
self._set_headers()
self.wfile.write("OSR API Active")
def do_POST(self):
print "received"
self._set_headers()
self.data_string = self.rfile.read(int(self.headers['Content-Length']))
inputData = self.data_string
print inputData
self.wfile.write("Received\n")
def run(server_class=HTTPServer, handler_class=S, port=1234):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print 'Starting HTTPD'
httpd.serve_forever()
run()
Broken pipe error message:
127.0.0.1 - - [11/Aug/2017 15:34:13] "GET / HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 56506)
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 657, in __init__
self.finish()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 716, in finish
self.wfile.close()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 283, in close
self.flush()
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 307, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
received
127.0.0.1 - - [11/Aug/2017 15:36:45] "POST / HTTP/1.1" 200 -
TestData
Screenshot of the chrome network tools

Sample JavaScript can't connect to Ruby WebSocket server

I would like to fiddle with websockets a bit. I installed a Ruby gem called "websocket-ruby" (https://github.com/imanel/websocket-ruby) I started a pry / IRB session and typed:
require "websocket"
#handshake = WebSocket::Handshake::Server.new(:host => "localhost", :port => 8080,:secure=>true)
This starts a websocket server as far as I know. Then I opened in my browser the Javascript HTML page which attempt to connect to the server:
<!doctype html>
<html lang="en">
<head>
<title>Websocket Client</title>
</head>
<body>
<script>
var exampleSocket = new WebSocket("wss://localhost:8080");
exampleSocket.onopen = function (event) {
exampleSocket.send("Can you hear me?");
};
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
</script>
</body>
</html>
But it says in the console log:
failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
I tried different ports both in server and in the client respectively: 8081, 12345, but I always get this error message.
I have some idea about websocket and javascript, but not websocket-ruby.
I hope it will helpful you.
In nodejs.. server.js file, write below code
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({port:8100});
console.log("websocket Server is Running...");
wss.on('connection', function connection(ws) {
// Store the remote systems IP address as "remoteIp".
var remoteIp = ws.upgradeReq.connection.remoteAddress;
// Print a log with the IP of the client that connected.
console.log('Connection received: ', remoteIp);
// Add a listener which listens for the "message" event.
// When a "message" event is received, take the contents
// of the message and pass it to the broadcast() function.
ws.on('message', wss.broadcast);
});
wss.broadcast = function(msg) {
wss.clients.forEach(function each(client) {
client.send(msg);
})
};
In javascript...
var SERVER_URL = 'ws://localhost:8100';
//instead of localhost you can also use IP address of your system
var ws;
function connect() {
alert('connect');
ws = new WebSocket(SERVER_URL, []);
// Set the function to be called when a message is received.
ws.onmessage = handleMessageReceived;
// Set the function to be called when we have connected to the server.
ws.onopen = handleConnected;
// Set the function to be called when an error occurs.
ws.onerror = handleError;
}
function handleMessageReceived(data) {
// Simply call logMessage(), passing the received data.
logMessage(data.data);
}
function handleConnected(data) {
// Create a log message which explains what has happened and includes
// the url we have connected too.
var logMsg = 'Connected to server: ' + data.target.url;
// Add the message to the log.
logMessage(logMsg)
}
function handleError(err) {
// Print the error to the console so we can debug it.
console.log("Error: ", err);
}
function logMessage(msg) {
// with the new message.
console.log(msg);
}
/** This is the scope function that is called when a users hits send. */
function sendMessage{
ws.send(msg);
};
connect();
in html use one button to send message to websocket server
<button onclick="sendMessage('Hi Websocket')">send message</button>
To the best of my knowledge, the Ruby code you presented does not start a Websocket server... what it does is initiate a server-side parser.
To start a server you need to use an actual websocket server.
ActionCable (with Rails) uses the websocket-ruby library to parse websocket events and it uses nio4r to operate the actual server.
Faye have a similar solution and em-websockets use the websocket-ruby gem with EventMachine.
Other Ruby Websocket servers include Iodine, which uses the C library facil.io. Iodine is used by the framework plezi as well as independently.
Since you were trying to run an echo server, here's a quick example using the Plezi framework (you can use it as middleware in Sinatra or Rails)...
...place the following in a config.ru file:
require 'plezi'
class WebsocketSample
# HTTP index
def index
'Hello World!'
end
# called when Websocket data is recieved
#
# data is a string that contains binary or UTF8 (message dependent) data.
def on_message(data)
puts "Websocket got: #{data}"
write data
end
end
Plezi.route '/', WebsocketSample
run Plezi.app
To run the server, call (ignore the $ sign, it marks this code as terminal code):
$ iodine
notice: Iodine requires a BSD / Unix / Linux machine, such as macOS, Ubuntu, etc'. It won't work on windows.

Error connecting to TM-U220

I have downloaded 2 javascript SDK for Epson printer that supports TM-U220, and both of them won't connect to my printer and won't print. But when I tried to use other SDK such as QZ Tray, it worked, but the QZ Tray must be turned on, I want this to work in android, so I use the javascript SDK from Epson.
The problem is when I use the printer sample that Epson provided in the javascript SDK and input the ip: 192.168.1.98, port: 9100, and device id: local_printer, I got this error :
connected to ePOS Device Service Interface is failed. [ERROR_TIMEOUT]
.
But the printer did a small printing, letter that I can't read, and at the very end of the print : 2http/1.1. And in the console :
OPTIONS https://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000 net::ERR_CONNECTION_REFUSED
and
OPTIONS https://192.168.1.98/cgi-bin/eposDisp/service.cgi?devid=local_display&timeout=10000 net::ERR_CONNECTION_REFUSED
I've also created my own simple code.
This is my first code using epos-2.3.0.js :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Print Test</title>
<script type="text/javascript" src="epos-2.3.0.js"></script>
<script type="text/javascript">
// Retrieving Printer objects (printer selection)
var printer = null;
// Retrieving Printer objects (printer selection)
// Creating ePOSDevice objects (device connection and communication)
var ePosDev = new epson.ePOSDevice();
function connect() {
var ipAddress = '192.168.1.98'; var port = '9100';
ePosDev.connect(ipAddress, port, callback_connect);
}
// Creating ePOSDevice objects (device connection and communication)
// Retrieving Printer objects (printer selection)
function callback_connect(resultConnect) {
var deviceId = 'local_printer';
var options = {'crypto' : false, 'buffer' : false};
if ((resultConnect == 'OK') || (resultConnect == 'SSL_CONNECT_OK')) {
// Retrieves the printer object
alert("Success callback connect");
ePostDev.createDevice(deviceId, ePosDev.DEVICE_TYPE_PRINTER, options, callback_createDevice);
}
else {
// Displays error messages
alert("Error callback connect");
}
}
function callback_createDevice(deviceObj, errorCode) {
if (deviceObj === null) {
// Displays an error message if the system fails to retreive the printer object
return;
}
printer = deviceObj;
// Registers the print complete event
printer.onreceive = function(response) {
if (response.success) {
// Displays the successful print message
alert("Callback create device response success");
}
else {
// Displays error messages
alert("Callback create device response failed");
}
}
}
// Retrieving Printer objects (printer selection)
// Creating print data (data buffering)
function createData() {
printer.addTextAlign(printer.ALIGN_CENTER);
printer.addText('Hello World\n');
}
// Creating print data (data buffering)
// Sending print data (printing and disconnection)
function send() {
if (ePosDev.isConnected) {
printer.send();
}
}
// Sending print data (printing and disconnection)
</script>
</head>
<body>
<input type="button" onclick="connect()" value="Connect" />
<input type="button" onClick="send()" value="Print Hello World" />
</body>
</html>
And this one I'm using epos-print-3.2.0.js :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Print Test 2</title>
<script type="text/javascript" src="epos-print-3.2.0.js"></script>
<script type="text/javascript">
function buildMessage() {
// Create a print document
var builder = new epson.ePOSBuilder();
builder.addTextLang('en');
builder.addTextSmooth(true);
builder.addTextFont(builder.FONT_A);
builder.addTextSize(3, 3);
builder.addText('Hello,\tWorld!\n');
builder.addCut(builder.CUT_FEED);
var request = builder.toString();
var address = 'http://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000';
// Create an ePOS-Print object
var epos = new epson.ePOSPrint(address);
//Send the print document
epos.send(request);
}
</script>
</head>
<body>
<button onclick="buildMessage()">Run</button>
</body>
</html>
When I run the second code, I got this error in my console :
OPTIONS http://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000
and
XMLHttpRequest cannot load http://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000. Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. The response
had HTTP status code 405.
But When I change the address from
http://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000
to
http://192.168.1.98:9100/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000
it printed me this :
OPTIONS /cgi-bin/epos/service.cgi?devid=local-printer&timeout=10000
HTTP/1.1 Host: 192.168.1.98:9100 Connection: keep-alive Access-Control-Request-Method: POST Origin: null
User-Agent: Mizilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Access-Control-Request-Headers: content-type, if-modified-since,
soapaction Accept: */* Accept-Encoding: gzip,
deflate,sdch Accept=Language: en-US, en;q=0.8
I was getting the same errors for a new TM-T88VI. Then I saw in the ePOS SDK User's Manual that in order to control a TM printer you need to enable the ePOS-Print setting from within the EpsonNet Config on the printer.
Looking at the manual in order to control a TM-U220 directly (without using a TM Intelligent printer) you'll need to have a UB-E04 or UB-R04 network interface installed. It says you can check which interfaces are installed by printing a status sheet.
From the look of it, this is a Cross Origin HTTP Request issue (CORS). This MDN article explains this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
I am guessing that the IP 92.168.1.98 is the printer IP (which is on the local network). See: http://trendblog.net/ever-wondered-use-192-168-x-x-ip-addresses-home/ and you can access it via port 9100 as described in your post above.
So since your actual web application is residing on a different IP than the printer IP and the way the web work, CORS is required when you are calling to a different IP / host so to prevent cross site scripting attack.
It's common sense that if the printer is exposing itself via port 9100, you should have that as part of your URI. That is the reason why http://192.168.1.98:9100/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000 works and the other one did not.
As for trying to access this via an Android device... the question is does the device is joined to your local network (192.168....) or is it on the Internet? If it is joined to the internet, I don't think you can access the printer which is probably not going to be exposed to the internet (having public IP). As long as they belong to the same network, they should be able to talk. If not, you will need to expose it to the internet (bad idea) or make sure they can see each other (Android connecting to your corporate WIFI and the printer can be reached via the WIFI).
I had the same problem with a TM-T20III. You have to use the utility software from Epson for your printer. In the advanced network settings, there is a menu which call "Filters" and I add the IP address of my POS as accept address.
But When I change the address from
http://192.168.1.98/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000
to
http://192.168.1.98:9100/cgi-bin/epos/service.cgi?devid=local_printer&timeout=10000
it printed me this :
Port 9100 is the raw input port of the printer, it seems to print the whole input request without interpreting it. ePOS Service seems to be available on ports 80 / 443.
I was getting the same errors for a new TM-T88VI. Then I saw in the ePOS SDK User's Manual that in order to control a TM printer you need to enable the ePOS-Print setting from within the EpsonNet Config on the printer.
Enabling the ePOS Print Service was the right solution for me. In order to do this, i had to update the firmware of the printer (TM-T88VI). In factory defaults, there was no option to switch on the ePOS Service.

Categories

Resources