I am writing a chat app with Spring Boot web sockets and Stomp on the front end. Is there a way to programmatically access context root of my application in JavaScript?
my application.properties:
server.contextPath=/chatapp
my js
function connect() {
socket = new SockJS('/chatapp/chat');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe('/user/queue/messages', function (message) {
showMessage(JSON.parse(message.body));
});
}
}
Now if I want to change application context in properties I will have to remember to change it in several places in the project which I am trying to avoid. So instead of hardcoding 'chatapp' in js I want to be able to extract it programmatically.
I know in jsp one can access context path through ${pageContext.request.contextPath} but I am using thymeleaf.
Related
I have 2 hubs that live on 2 different servers. Ideally I would like my series of webpages to connect to attempt to connect to 1 of these hubs, then if it fails switch to the other hub. Is this possible at all.
I can't use the traditional method to connecting to the hub like so:
<script id="hubScript" src="IP:port/signalr/hubs"></script>
$.connection.hub.url = SIGNALR_HUB_SERVER_1;
srv = $.connection.tcpHub;
since I don't know which hub I will be connecting to, or which hub will be alive.
Example of code that I have tried for reference
if (document.head.getElementsByTagName("script").item(i).src == SIGNALR_HUB_SERVER_1 + "/hubs") {
$.connection.hub.url = SIGNALR_HUB_SERVER_1;
}
else if(document.head.getElementsByTagName("script").item(i).src == SIGNALR_HUB_SERVER_2 + "/hubs") {
$.connection.hub.url = SIGNALR_HUB_SERVER_2;
}
When I try and connect using this code I get the error: "Error loading hubs. Ensure your hubs reference is correct". This is because my script tag that contains the url is not the same as the url that I am trying to connect to.
I'm new to the subject area so sorry If I've not explained things well.
I created a web API client that sends strings from my HTML (imbedded with JavaScript) back to a node.js server using Web Sockets.
I then swapped out the node.js server with a C++ application that still receives the string data perfectly.
My JS Client(within html script) :
function SendWSData(){
const ws = new WebSocket("ws://localhost:PORT");
ws.addEventListener("open", () => {
console.log("We are connected!");
const stringvalue = `this is a test string`
ws.send(stringvalue);
});
ws.addEventListener("message", ({ data }) => {
console.log(data);
});
}
My C++ Server:
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
using namespace std;
using tcp = boost::asio::ip::tcp;
string stringVal;
int main() {
auto const address = boost::asio::ip::make_address("IP");
auto const port = static_cast<unsigned short>(std::atoi("PORT"));
boost::asio::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, port}};
tcp::socket socket{ioc};
acceptor.accept(socket);
std::cout<<"socket accepted"<<std::endl;
std::thread{[q = std::move(socket)]() mutable {
boost::beast::websocket::stream<tcp::socket> ws {std::move(q)};
ws.accept();
while(1)
{
boost::beast::flat_buffer buffer;
ws.read(buffer);
auto out = boost::beast::buffers_to_string(buffer.cdata());
stringVal = out
std::cout<<"stringVal = "<<stringVal<<std::endl;
}
}
This reads data coming into the buffer, and assigns it to a string variable on my C++ app, for me to use.
My question is how would I go about sending back a string to the web page from the C++ app? (especially as my web page is the client and the C++ app is the server)
I know that the server is meant to return a response which is standard, however does that change if I'm trying to implement a function based response? I want to generate a button on the webpage and textbox, and when clicked I get string data from the C++ app.
I've not found much online about sending data from server back to client, as I'm trying to get a request (which is the behaviour of a client). (Could I possibly generate another Web Socket and swap the roles of my web API and C++ app for this particular case; possibly multithreading it?)
I've tried to use the microsoft teams client SDK to get access to the current context of the tab. As of yet I haven't been able to get the getContext callback to run let alone return a context that I can use in any meaningful way.
I've tried to create a static html page that uses the client SDK by embedding the script and then log the context of the object. The SDK properly returns an object of the expected shape, but using initialize() then getContext() does nothing. I'm making this website as a tab inside of Microsoft teams creating a new tab and making it a website tab.
<p>hello World!</p>
<script src="https://statics.teams.microsoft.com/sdk/v1.4.2/js/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
<script>
console.log(microsoftTeams);
microsoftTeams.initialize();
microsoftTeams.getContext((context) => console.log(context));
</script>
This is the static page I'm using to try and get context logged out to the console.
const http = require("http");
const fs = require("fs");
this.html;
fs.readFile("./src/index.html", (err, html) => {
if (err) {
throw new Error(err);
} else {
this.html = html;
}
})
http.createServer((req, res) => {
res.write(this.html);
res.end();
}).listen(7777);
This is my server I'm using to return the static html
I'm using ngrok to provide a tunnel from the web to my local server on port 7777. I can get the page to load just fine, but have yet to get the getContext() to run my callback function.
I expect to be able to get the context of the teams tab in the callback of the getContext() function, but that function never runs.
Moving answer from Comments section:
Tab created using default Website App doesn't get the Teams context, it needs to be a trusted URL. You need to build custom Tab to get context for your Microsoft Teams tab.
Please take a look at steps to create Teams App manifest using App Studio.
In the default application specified Hello World with Node.js if you put this script in the end of body tag.
console.log(microsoftTeams);
microsoftTeams.initialize();
microsoftTeams.getContext((context) => console.log(context));
Now you have to run this application in Teams environment only then this context method will get a value and not on regular html page.
Scenario
C# Based Server
JavaScript Based Client
Situation
I created this fairly simple "server" which only job is to help me understanding how to actually use those websockets in a C# environment.
using (var server = new HttpListener())
{
server.Prefixes.Add("http://localhost:8080/");
server.Start();
while(true)
{
var context = server.GetContext();
if (context.Request.IsWebSocketRequest)
{
var cntxt = context.AcceptWebSocketAsync(null).ConfigureAwait(true).GetAwaiter().GetResult();
var buff = new byte[2048];
while(cntxt.WebSocket.State == System.Net.WebSockets.WebSocketState.Open || cntxt.WebSocket.State == System.Net.WebSockets.WebSocketState.Connecting)
{
cntxt.WebSocket.ReceiveAsync(new ArraySegment<byte>(buff), CancellationToken.None).ConfigureAwait(true).GetAwaiter().GetResult();
Console.WriteLine(Encoding.UTF8.GetString(buff));
}
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
using (var writer = new StreamWriter(context.Response.OutputStream))
{
writer.Write("<html><body>WEBSOCKET ONLY!</body></html>");
}
}
}
}
The problem now is: when i try to add the websocket prefix via server.Prefixes.Add("ws://localhost:8080"), i get some System.ArgumentException thrown which tells my i can only add http and https as accepted protocol.
Thing is: doing it and using ws = new WebSocket('ws://localhost:8080'); (JavaScript) to connect to a websocket, yields for obvious reasons nothing.
Changing the prefix to HTTP in the JS websocket, will provide me with yet another sort-off argument exception.
Actual Question
how to actually get the HttpListener to acceppt web socket requests?
Further Info
Used .net framework is 4.6.1
Browser to test this was Google Chrome 69.0.3497.100
The reason for why the above was not working ... is due to the JS websocket requiring a path.
Changing the above HttpListener prefix to eg. "http://localhost:8080/asdasd/" will allow the socket to connect propertly.
I am currently building a win-store app for a client, and I can't seem to figure out how to link to another app from within my current app.
I have seen plenty of documentation on how to open the default application from a URI or file type but nothing on opening a specific app.
Currently I am able to open my app with the function below, after adding a protocol to the declarations in my package.appxmanifest, but this isn't the preferred solution since this will not cause the app to open in full screen.
function openApp() {
var options = new Windows.System.LauncherOptions();
options.preferredApplicationPackageFamilyName = "packageFamilyName";
options.preferredApplicationDisplayName = "App Display Name";
var uri = new Windows.Foundation.Uri("linktomyapphere:");
Windows.System.Launcher.launchUriAsync(uri).then(
function (e) {},
function (err) {
console.log(err);
});
}
The best way is definitely URL activation (aka protocol activation). If you own the other app, you register a protocol for it - something like myapp://. That is done in the manifest. Then you follow the instructions on this page to activate that from your app. You can even pass URL parameters so you can pass some state in during activation.