Azure Functions and SignalR with Anthony Chu
>> Well, good morning. Good afternoon. Good evening. Depending on where in the world you happen to be.
My name is Christopher Harrison. Welcome to Web Wednesday, the show where I bring on people that are much smarter than me to talk about cool things, web dev. Today I'm actually very pleased to bring back on Anthony Chu. If you haven't already seen Anthony present or just talk about technology, he's fantastic. He's absolutely brilliant.
He's really passionate and knows probably more about doing serverless codes, serverless computing, and Azure functions than I will ever know. He's always just a fantastic guest to have. Today he is coming on to talk about a really cool little service called SignalR.
If you're not familiar with SignalR, what SignalR allows you to do, is to do real-time messaging. That way, if I want to maybe enable chat or if I want to do something where I've detected that an event has occurred on the server and I want to be able to send a message down to a browser-based client, then SignalR can do those types of things for you. It's a really neat both SDK as well as service. It can also help simplify doing what would typically require a fair bit of code if you are going to do this natively using WebSockets. But you didn't come here to hear me talk about it. You came to hear Anthony talk about it.
Let me bring Anthony on. Anthony, thanks again for joining. It's always wonderful to have you on Web Wednesday to chat about anything and honestly, it's always fun to chat with you. >> Yeah, thanks for having me back. Yeah, I had a great time last time.
Yeah. Looking forward to this. >> Yeah. Me too. Because I know that you've got a really cool demo that you're going to take us to in a few minutes.
Let's start here. What is real-time messaging? What does this mean in the Webspace? >> In the Webspace, we're typically talking about things like WebSockets. But in the early days, there wasn't WebSockets. The first thing that we probably did 10, 20 years ago was just keep pinging a server to see if there's any new messages.
Quite inefficient, but it gets the job done. Then we figured out new ways of doing it. There's a technique called Long Polling, where you open a connection to the server and the server doesn't respond until there is a real-time update. It's a little bit more efficient and keep pulling all the time over and over again. Then for a while there, and I think it still exists right now.
There's a technology called server-sent events, that you can also use to push real-time messages from a server to a client like a browser or even a mobile app. Then in the last five, 10 years, WebSockets is gone everywhere. That seems to be what everyone is using these days.
You can actually work with WebSockets pretty easily just by using this plain JavaScript in the browser and connecting to a WebSocket. But a library like Socket IO or SignalR which you're talking about today is actually like an abstraction on top of it, I guess you can say. What that means is that instead of actually working with the raw web sockets and actually working with the frames, sending frames to the server, getting frames back from the server. You're actually working on one or two levels above that. You end up doing things like sending messages from the server to your client. Very much like you are just pushing a message to a queue or something like that, or even just doing like a remote on a procedure called thing.
It's a lot more natural. Then you can also have access to higher-level concepts, you can put a connections into groups. Or just basically create arbitrary grips. Instead of keeping track of whichever your users, which have connections happen to be from say, Seattle. Then you only want to send a message to only people in Seattle, without a library like that, you have to manage all that yourself.
Then when you need to send it, you actually literally have to iterate through all the different socket connections, WebSocket connections and send these messages down. Whereas with both Socket IO and SignalR and other like libraries like it, you're literally just make a call and say, hey, send this message to this group and then it just does it. A lot of the group and user management, it's all done for you.
Another thing that stuff like this will do for you is that you don't have to worry about what my clients, whether it's could be a super old browser. It could be, a fairly old phone device that might not actually support WebSockets. These libraries will actually fall back to the other methods that I mentioned before, like server-sent events, we have a Long Polling. You still program exactly the same way, you say send a message, but it figures out for that connection which protocol to use.
You don't have to worry about it, and then reconnections and stuff like that. >> That way if for whatever reason my browser didn't support WebSockets that it's still able to funk down to an earlier technology and guarantee me then I'll be able to "Send" a real-time message even if it's not actually doing it with a real-time stack. >> Yeah, exactly. >> Okay.
>> Yeah. >> We've mentioned that the WebSocket is this cool, new thing. What is WebSockets, and how does that compare to HTTP or HTTPS? >> Yeah, so it's a bidirectional protocol. You can actually send messages from the server to your client, but clients can also send messages upstream. That's really the main difference.
If you look at the actual protocol itself, you go very deep into the differences. But for day-to-day use, that's really all you really need to know. You're sending these frames back and forth, down this bidirectional channel. >> I'm just going to simply say HTTP, but as opposed to just like normal HTTP, where what I'm going to do is I'm going to make a request via post getter or whatever it is, and then get a response back. Then once that's done, then we basically tear down that connection and that's it. With WebSocket that it sounds like I'm going to be able to almost treat it like it's on my network from what it sounds like, as if I was just able to just do a little TCP signal to it only instead obviously, it's a web-based protocol.
Where now I'm able to send a message up to the server, and then the server is at some later point able to send a message back down to me. >> Yeah, exactly. >> Okay. All right.
I can get behind that. SignalR then, you mentioned that it's an SDK, that that's something that can help make it easier for me to start programming with WebSockets. >> Yeah. It's an SDK that came out of the ASP.NET world. You actually don't need ASP.NET to
use it now that's we have a service, and that's what we're actually going to talk about today. We're going to talk about how we can use JavaScript and Python code running in serverless functions and Azure Functions to work with SignalR service to basically get the same capability in other languages. As an SDK, I think there's multiple languages that we support in terms of clients. So web is obviously covered with JavaScript and TypeScript. But there's also, a Java client, there's the C++ client and throughout the community there are different clients that are produced in open-source for things like Swift and Python, and things like that. >> That's interesting. So then from a client-side,
I'm not bound to only use a browser, that I can also be using a fat client like I could be using a phone app or I could be using a desktop application, and still be able to communicate with SignalR. >> Yeah. It's quite flexible that way. You've got to mention mobile. One of the things that people quite often will get confused by a little bit, when talking about WebSocket technology is that this is not the push notifications on your phone that we typically talk about. That's typically very specific to whether using Apple or Google and stuff like that. That's totally separate from WebSockets.
WebSockets is when you have your app open, say you open up a map, for example. For instance, you're looking for a car share and you see the little cars moving around the map, that's probably WebSocket. But when you close the app and you exit out, and then you get a notification from the app saying that your driver's here, that's typically a push notification that sent another way. That's not what we're talking about today.
>> Then I guess it also bears highlighting the fact that this is also different from those browser notifications that everybody is going to say no to that that's not what we're talking about when we're talking about WebSockets. >> Right. Yeah, WebSockets is not annoying like that, no. >> Okay. Cool. WebSockets is really about being able to maybe create a chat application or that maybe there's a long-running process like maybe I'm placing an order doing something like that. The server's now going do a few things. It's going to take maybe 15, 30 seconds, a few minutes, and then now it wants to let me know that that's completed, that it can do that with WebSockets.
I'm also thinking maybe if I'm watching or if I'm following a sporting event, and somebody has scored, if I've got the page open, then it can refresh the page then or update that piece of data using WebSocket. >> Yes. Exactly. There's just so many uses for it now. We don't even think about it anymore. When you open up a web page, just expect things to just happen without you pressing the ''Refresh'' button. I think we pretty much take that for granted now. >> Yeah, I'd agree with that.
Zimbabwe Dungeon Master, which is a great name, asked the question, ''Is SignalR good for server to server communication, say for an old project, whether its no gRPC." >> Yeah, I think that should work fine. You obviously have the weigh the pros and cons. You definitely have the [inaudible] due to the protocol. So as long as you own both sides, it's typically not too bad.
If you cannot, if you want external services to connect to your service quite often, like an old-fashioned HTTP REST API type of thing, it'll be easier for other services to use without binding yourself to a specific library like SignalR or Socket.IO. It works well for that purpose. I've seen people use it, for generic API for service, we do typically see people fall back to using HTTP APIs. >> That makes sense. Again, the key difference is we're always looking for the need for two-way communication.
If all that I need to do is make a request, I get a response, and I'm good with that, then we can just again go back to HTTP. It's really if I'm looking for that ability to have two-way conversations. Now, you mentioned the SignalR Service. What is the SignalR Service? >> It's a service in Azure that basically makes it really easy to use SignalR without you needing to write an ASP.NET app and creating it. Or spinning up Express app and using Socket.IO, and they have access to a library, like Socket.IO or SignalR.
So you can spin up an instance of SignalR Service in Azure, and there's actually a free tier so you don't have to pay for anything. You can use it for up to like 20 connections or something like that, which is plenty for a lot of apps, and that's it. You don't have to worry about managing anything like that. Your clients will connect to that, and we need to send messages to your client behind the scenes if your using Azure Functions. There's actually some output bindings that you can use in Azure Functions that makes it super easy with a single line of code to send these messages out. You don't even need to figure out how to talk to the service behind the scenes.
We just do everything for you. >> Since you mentioned Azure Functions, I'd be remiss if I didn't then ask about Azure Static Web Apps, which if anybody's not familiar, Azure Static Web Apps is probably the best thing that we've released since Visual Studio Code, which I know is a bold statement. But it gives you that ability to run those types of applications where the bulk of your code is going to be on the client-side, which is really how we do modern web dev these days. That you get that and your server-side code using functions in one very nice, neat package.
I'm guessing then that the SignalR Service would be able to work then with Azure Static Web Apps as well. >> Yeah. Hopefully, we'll be able to show you an example of that running an Azure Static Web Apps, actually working with the authentication in Static Web Apps.
Like the SignalR team always makes fun of me for doing chat demos, but I will show you a chat demo. I do find that with chat it is overdone in a sense, but also it is probably the easiest concept. I'll not explain to you what a chat app is.
I'll just show you the code. I think it's a good way to show you how SignalR works. Then we'll go into other things. I do find that show you some more interesting stuff, though. >> Yeah. You know what, there are certainly those stock standard demos that everybody goes to.
But sometimes, everybody goes through it for a good reason. Now, what's great about that chat app, like you said, is not only A, does everybody know what it is, but B, it makes it really easy for me to be able to demo. I don't need to do anything fancy. I just type something here and then poof something happens over here, which is really the effect that you're looking for. >> Yeah. Should we take a look at how to do this?
>> Actually, I'm going to throw in one last question from Andrew Ha about SignalR Service, ask if it's instance-based or serverless? >> It's instance-based right now. Although I think it's a pretty common request for them to offer consumption-based pricing, so per connection. Currently, it's not. If you need to go over that, there is a fixed Instance price that you go up to. I'm not sure whether or not they support auto-scaling yet.
You do pre-provision these things called units, and each unit gives you like a thousand connections. But I know it's definitely on their roadmap to see if they can support consumption-based pricing. >> Then Egoist asked if SignalR requires an implementation using Async/await . >> No. I think those two concepts are probably a little bit orthogonal. Yeah, there's nothing like in SignalR itself that requires Async/await.
>> Okay. >> Yeah. But typically, most of the SDKs do return promises or tasks in C-Sharp, so you end up using Async/await with it. But I don't think there's anything that requires you to use Async/await.
>> Okay. Fair enough. >> Yeah. >> Let's take a look at some code here. >> I think the first thing we're going to do is because it's going to take about a minute or two just to create a SignalR service, let's do that.
I'm in the Azure portal. It's fairly easy to do. I'd search for SignalR and then I'd say I want to new thing. I'm just going to go and create a new resource or webwednesday. Maybe I'll call it webwednesday. >> Very creative in the names.
I appreciate that. >> I try my best. Actually, when I code or well, now as a PM, I code less.
Naming is the thing I hate the most. I always ask someone else for naming. >> I feel that. >> I'm going to pick a location nice and close to me. Then I'm going to pick the free tier. Hopefully, this is big enough. I'm trying to make a pick here.
>> There you go. >> There's the default and classic. I don't need to explain to you what they are because we're not using them today. We're going to use a serverless one. That's the one where we can use with Azure Functions.
>> Okay. >> Then I'm just going to go ahead and create it after the button lights up. I'm going to go off and get created. I think in probably a minute or two, we should have one.
>> Okay. >> While that's happening, let's take a look at how we can work with it from Azure Functions. >> Let me actually sneak in a real quick question here. Zimbabwe dungeon master asked the question, how big is the message buffer? Is it per hub or per group? >> The message buffer? I guess it really depends on what we mean by message buffer. I think in the past, SignalR has had the ability to support like when you disconnect accidentally or on purpose or whatever.
When you reconnect, the messages that you missed will get replayed to you. Well, not really replay because you never got it the first time. It will get sent down to you. There used to be a buffer there.
I believe in the latest versions of SignalR both are really memory intensive and also really hard to get right that we stopped supporting that. Typically, the pattern that I see people use and I'll show you later on a more fuller-blown web app, is that when you reconnect, you go and reach out to a different endpoint. Or maybe when you reconnect, on connection, that the server, or in this case, a serverless function will actually send you the latest updates.
>> Okay. >> For instance, for a chat app, when you connect, the first thing you do is say, "Hey, give me the most recent chat messages so that you can repaint your screen and then start listening for new ones." That seems to be a more scalable and easier reasonable way of supporting buffers versus actually creating a buffer for every connection and then worry about how to get rid of it and stuff like that. I hope that's what they meant by buffer.
But if not, please ask. >> Okay. That sounds good. Let's build an app. >> I'm going to assume a little bit of knowledge of Azure Functions.
Even if not, I'll try to walk through a little bit of it. In Azure Functions, the first thing that you need to do is create what's called an app and then within an app, you can have more than one functions. These functions are serverless. I'm going to be running these locally on my machine right now and then some of the other demos I'll show are actually going to be running in the Cloud. >> Okay. >> First thing, I'm going to do is I'm going to say create a new project.
This is using the Azure Functions extension and VS Code. I'm going to choose this folder that I already created. I will use Javascript. Let's see. What should I do? I need to switch to a different set of templates so I can see everything.
I'm going to choose this thing called a SignalR negotiate HTTP trigger. It's a really long name. Funny enough, I think I added this item to this menu and I named it.
See, I shouldn't be trusted to name anything. I'll quickly talk about what the negotiate thing does. You can ignore it when you first get started with SignalR.
For basically the browser or the client to figure out where your SignalR service is, it needs to first call an endpoint to figure that out, and that's what the negotiate endpoint does. It's actually part of the SignalR protocol. The first thing that it does is it's actually going to make an HTTP post to an endpoint. By convention, it needs to be named negotiate with documentation and all that. But then you don't have a do a heck of a lot in an Azure Function app for this to work.
You can see that using a template, we already created an HTTP function. This function will just become an HTTP endpoint in the Cloud. Because the route is negotiate, it's going to be at slashed, whatever HTTP, whatever domain name I get for my function app slash, API, slash negotiate and soon our service will just know how to talk to it. I'll show you that piece of the code in a bit. Then down here, we're basically getting access to this thing called a connection info. What this thing does is that it gives you this payload that you need to return back to the client so that it knows what to do with it.
Again, you don't have to worry too much about how this works because most of it is done for you in the bye-bye to templates. But you do need one of these things. Typically in here, if you need to assign a connection to a group or you need to associate a connection to a user so you can send messages that are only going to be received by a user, you might need to do a little bit more stuff in the negotiate function. But typically if you just want to do a broadcast to everything that's connected, you don't really have to do anything here, it's going to take everything as is and that's that. Should I run it? I'll run the whole thing in a bit later.
The other thing that I want to show you now is with a negotiate function, what that allows the browser or any client to do is to connect to SignalR service. Actually, the real thing that your app wants to do is actually, when something happens, whether it's because you receive an HTTP request into your function app or your function app could be listening for queue messages, for example, and then every time you get a queue message, you want to broadcast that out over your WebSocket. Or it could be a change over Cosmos DB or if it could be a change in blob storage and basically, any trigger that you can set up. In Azure Functions, you can basically turn around, and when one of those events happen, turn around and send a message to all your connected clients over SignalR.
I've seen stuff, for instance, moving stuff around in a map. Imagine you can an event every time an airplane moves in the sky. You can actually take that and broadcast that out to browsers and then you can actually paint that plane moving on a map, so things like that.
It's pretty flexible. But for our purposes here, because we are building a chat app, I will just create an HTTP endpoint. How do I do that? Say Create Function and then I just want an HTTP function. I'm going to call it messages and anonymous is fine. We don't need security for a demo. Let's see. What should I do? This is just a plain HTTP trigger.
It's going to become an endpoint as /API/messages. The idea is that every time we want to send a message, we can post to this endpoint. The body of the message will be the message itself, I guess. >> Okay, so people then aren't going to call the negotiate directly. They're going to do everything then through this Azure Function.
>> Yeah. This is the thing that actually does most of the work, which is relaying a message from one client to everybody else. It'll make maybe a little bit more sense once we fire it up and see it run. But what we need to do now is we need to use what's called an output binding for this.
I can say Add a binding. I want an output binding, and I want a SignalR binding. Then the naming thing again.
I'll call it messages or new message over that. I'm going to say default here, but I'll tell you why. SignalR has a concept of hubs. You can actually divide a single SignalR service into multiple hubs. So you can try and think of them as namespaces. If your app happens to support both, like a real-time chat kind of a thing but another part of your app might support a little real-time notification, little like changing the number of messages that appear in the corner of your screen or whatever it is.
You can actually have two different hubs we call it to take care of each of those types of messages. You don't have to worry about using a single hub in figuring out whether this message is actually a chat message. This one is actually a notification. You don't have to worry about any of that. You can divide it up into multiple namespaces. I'm going to call this one a default and I'll tell you why in a sec.
Then I need to just give it a setting name. I'm going to call it AzureSignalRConnectionString. Absolutely long name.
>> That absolutely is going to be on the server or in Azure, I shouldn't technically say on the server because it's serverless. But that's where it's going to sit there and it's going to store then the location of that SignalR server, correct? >> Yeah. It's going to be a connection string. It's going to conclude both the location of it as well as a Get key. >> Okay. >> Then the app setting value, I'm going to skip that for now because I need to figure out what that is.
I'll probably want to do this off-screen because I don't want to show you what that is. Yes, that's done there. Also another long name. Again, I came up with that name.
Basically anytime you see a long name, I probably has something to do with it because I couldn't figure how to make it shorter. >> I'm okay with long names. If it's something that's going to be automatically filled or especially if it's something that there's some form of an autocomplete or IntelliSense, long names are okay. I would much prefer a longer name that describes what it is, than a short name where I'm having to figure out what the world it's supposed to do. >> Okay, that's good. I named this binding newMessage.
In here now I can pretty much get rid of all of this. The first thing that I want to do is get access to the body of the request. I'm going to say const, just message equals request.body, I think. Well that'll give me basically the body itself.
I actually don't really want to do anything with it. You can do some validation in here if you want or you probably should because anyone can send anything to this thing. But again, demo, no security.
I'm just going to relay this back to all the connected clients. In order to do that, I would have to talk to the context which gives me some bindings. Then for newMessage binding because that's the name I gave the SignalR output binding.
I am going to assign it to an object. I can actually assign it to an array if I want to send a pile of messages out all at once, I can actually use an array of these objects, but I'm only going to send one. So I'm just going to just have an object. This object takes two things. Again, this is all in documentation, so you don't have to worry about memorizing it like I have here.
The first argument, I guess that it needs, it's sync all the target, and that is really a name of an event. I'm actually going to call newMessage as well. Plus this is an event's name. You don't have to worry about too much why or what that is. Then the arguments is an array. Then I'm just going to pass the message.
That's only going to have one argument, but it can have more. >> Okay. >> That's it. That's really all the code
that we need to send that message. One thing that I'll do here. >> Really kind if breaking the case for using TypeScript here. Because then I could create the interface for what newMessage is going to be and I can then of course know what my rack is because I can add in the Typein to know all of that.
If you haven't already started using TypeScript, you should definitely use TypeScript. >> Yeah, I'm okay with TypeScript. I think we had this conversation last time about how I have, I won't say love-hate relationship but I'm like I can go both ways. I like the simplicity of the JavaScript as well.
I'm just going to create a very simple HTML page here as we're chatting that show you how to now use an HTML page to connect to SignalR service. I'm going to do a couple of things before that. In my local.settings.json, this is where we configure that Azure SignalR connection string and this is where I'm going to type off-screen here. I'm going to whoop go over here. But that still leaves us here.
I'm going to go over here as well. I'm going to go over to, actually, I'll show you what this looks like. My resource is created. Then see, I'm going to click on "Keys". Okay, I'll be back. Then I will copy the connection string. I'll get out of the keys.
I'll give them back to there. I'm going to paste in my connection string. I'm going to save it, and I'm going to bring this thing back on this side. You can see that I pasted into connection string and you can't see the key.
>> Perfect. >> Now all this serverless, server-side stuff will work because that key is there or that connection string is there. I'm going to quickly do one thing here. I'm going to go to this JavaScript CDN called JSdeliver. There's actually better ways of actually acquiring the SignalR SDK for JavaScript.
You can NPM install if you have a full-blown React app. But I'm just lazy. I'm going to search Microsoft SignalR. There it is. I'm just going to browse to the browser version of the thing, and I'm just going to copy the HTML. All that's going to give me is a really simple script tag that brings in SignalR. But like I said, if you're using React or [inaudible] , really anything that compiles, you would be referring to NPM package instead.
>> Wasn't there an ASP.NetCDN for quite a while? >> Yeah, there is. >> Is it still there? >> One of the things that we wanted to do with SignalR, and this is quite a while back, is that we wanted to couple it from ASP.Net so that people don't get the false impression that it's only for ASP.Net. >> That makes sense. >> Yes, this actually used to be scoped to @ ASP.Net,
but we changed it to @Microsoft just to make it a little bit more agnostic. But there probably is an CDN somewhere. JSdeliver is actually a really easy way to really have an http endpoint to any file that's in NPM package or even in a GitHub Repo. It does all that stuff for you.
So you can just reference it. Quickly I'm going to show you what what you get to do here. I'm going to go and say const, connection, equals newSignalR.HubConnection. This is where IntelliSense will come in if you actually use an NPM package. I don't get that, so hopefully I'm doing it right. >> I am going to bring you over to the dark side.
I want to bring you over to TypeScript. >> Yeah. I'm going to put /api here. What this means is that I'm telling the SignalR library that my hub endpoint is going to be at /api.
Then by default it's actually going to attach /negotiate at the end of it, the figure of what the negotiate [inaudible]. That really works is that just by saying /api it will find the right negotiate endpoints that I created over here. Then I can also say something like with automatic reconnect so that you don't have to worry about what happens if the connection drops momentarily. It'll just do the reconnect for you. The last thing I'm going to do is I'm going to say .build. Then I'm also going to go connection .start.
This thing returns a promise if you're going to want to wait for it and see. They say connected or whatever you can do that. I'm going to be lazy and not do that. The only thing I have to do now is that I've established the connection. What I want to do is listen for that new message, I guess. The then new message event so that I can do something with it.
I'm going to say connection.on newMessage. Then I get [inaudible] function in it and then the message is that argument that I passed on the server-side. Then I suddenly do something with it. I'm going to be lazy and just be like console.log(msg). That's it. But you can imagine this updating the UI and doing something way more fancy than console log. But I think this should more or less work.
I'm going to go ahead and you mentioned the Static Web Apps earlier. Static Web Apps we're actually working on a local emulator experience so that you can actually serve a locally spin up as single server that both spheres your static assets, as well as starts up the functionality. Basically, the two parts of a Static Web App both working together at a single endpoint locally. So I'll be using that to start up my app here. My app consists of my Index.html plus some functions. I think I'm in the right place.
I'm going to say Static Web App, swa, starts, and I want triple w as where my Static Web App is. Then I want to say, I hope this works. My API is here. So that works. Oh no. We're already running this. I'm going to find my browsers. It's over here. Oh, it is.
That's the next demo. Here we go. Is it going to work? >> That's funny. >> Starting up Azure Functions, it's also starting up my front end as well. So I can go to this 4280 endpoint locally.
I'm actually going to open up my console because everything's going to be happening in there. I'm going to go localhost 4280. Oh, no. An action argument is required.
This is the unexpected part. One second. Connection equals new SignalR Hub Connection Builder. How do I know that? Apparently, not enough time though. There we go. Don't ignore that fav icon thing, that's fine. >> Yeah. >> I'll quickly show you what happened here.
If we look at the network. Let me make this full size. What we've done is that we started with a thing called the SignalR thing.
But you can see that we're making a request to the negotiate end-point and this negotiate endpoint actually comes back with a couple of things. The location of the SignalR Hub or business SignalR service, as well as a token that the SK can use to connect to it. You don't have to know anything about this at all. This is like behind-the-scenes, how it works. >> Okay.
>> Then it's going to go, now you can see that it took that endpoint and it's now calling it. I don't know if you can see it on the mouseover. >> There we go. >> I may do it and maybe not because I don't know how much I'm sharing. Sometimes it's not coming through. >> No. It's all coming through just fine.
>> Okay. Great. Then this last one here you can see that this is the final WebSocket connection that's made after it's connected in that negotiation dense. This is the only thing that we really care about. If you look down here, you can see some messages. I'm going to hope that this thing is actually working. >> If you go back to that real quick, there was one little thing that I wanted to highlight there, go to go back to that WebSocket.
The protocol there is different, it's WSS which is WebSocket secure like HTTPS there, but that's you saying WebSocket is a different protocol from HTTP. >> Yeah. Typically you start from HTTPS connection and then you upgrade to a WebSocket and that's what's going to happen here. >> Okay.
>> Cool. I'm going to take a look at the messages that are coming through here. I don't know how to make it bigger. You can see that it stops coming down, the search just pings from the server to make sure that we're still connected. I'm going to go back over here and just really quickly make an HTTP request to it.
I'm just going to do it. You can [inaudible] for it, I'm going to just do it within VS Code. I'm going to say POST http://localhost:4280/api/messages.
How do we know that? We've gotten that before. Content-Type is application JSON. I'm even over with that. Then I'm going to pass just like hello world message. >> Hold on. What are you doing here? I've never seen this in VS Code.
>> This is an extension called HTTP REST client. What it allows you to do is basically type the HTTP message and click it. Then you can see that it worked. Now if I come over here, you can see that I got that WebSocket frame as well in my console. I got that thing printed out. >> Yeah.
>> That's how it works. I don't know what else I'd show you, but I guess I can do more, I can open up multiple browsers and you can see that they all receive the message. But at its core, that's how you create the functions that are needed for you to support SignalR. Then also a webpage that makes that connection, it actually listens to the messages.
Now it's really just up to you and what you want to do with it. That's it. >> Okay. >> Then I can show you a more full-blown version of this.
What's a good way to do that? I can go to GitHub. Not that. Let's go to GitHub. >> I'm still stuck on that REST client, I'm blown away by that extension. It's now immediately going to be my favorite. >> That's nice. I can commit those things to my source control. >> Right. >> It's great. I was quickly going to show
you how you can turn this into a full-blown chat. [inaudible] is another function app, but it's got the same negotiate endpoints nothing special there. I think that even the send message is about the same. It does a little bit more because this is running in Static Web Apps. It's actually going to parse the headers to figure out what the actual color is, the user detail so they can't spoof that, they're logged in.
So I'm pulling out their user detail and I'm actually setting that as their sender. Basically sending the sender to that username. You're securely sending these messages. So when you see the server saying this message came from Anthony, it really did come from Anthony. But aside from that, it's really the same thing.
Remember the target and arguments thing, doing exactly the same thing as before. Then there's actually one more thing that we're doing is that my function.json, I have an output binding for table storage as well so I'm saving these messages as well and that's done by this line of code.
Visit this line of code and this line of code will seize the message to a storage or to a table, as well as broadcast the message everywhere. It's really easy to use. Then like I was talking about before, when you first connect, you need to get the message history. I have an HTTP trigger table basically saying give me the latest 50 messages. Then the code is really one line of code, I'm just going to return all those messages back to the browser.
I think we have maybe 20, 30 lines of code in the server-side. That's going to be everything that you need for this app to run. Then I'll show you the HTML as well. This is using view so just a lot of HTML stuff, but really down here you'll recognize the connection stuff. You'll recognize me setting up a listener for the new message. This is [inaudible] , I'm posting my endpoint.
Authenticated user, don't worry about that. A little messages history. When you first startup, we're going to make a get to the messages endpoint. That's going to return message in the table. That's really all it is. I guess there is a standard view out.
Then if I go to chat on anthonychu.com, you might already be logged in, [inaudible] . Let me log out. There's a Static Web App. >> That log in, log out that you're using is that's something that's built into Static Web Apps or you're using the Graph Toolkit? >> This is actually completely from Static Web Apps. I didn't really have to do anything.
When I click this button, I'm actually literally just redirecting to the login endpoint for Static Web Apps. >> Okay. >> Because I'm already logged into GitHub it's going to bounce right back. You can see that I'm logged in.
I tested this four months ago, but still works, testing. You see it works even if I copy this and open up a new browser, paste that in, come back over here. Say, "Hi", You can see that both browsers are good. It's really easy to do and it works. So that's how build a real-world app with it and it's really straightforward to deploy this to the Static Web Apps. >> Okay. Then I can go and sign in with my GitHub.
Of course, I'm going to need to MFA real quick here. Chaga, chaga, chaga, boop, boop, boop, boop, boop, boop, boop. >> I'm excited and I'm waiting. >> I'm going to authorize it, grant consent.
Anthony now owns half of everything that is mine. It worked, there it is. Very cool. >> Nice. That is awesome. I wasn't sure if that was going to work.
I don't know why. Maybe it's because I wrote it so who knows what's going to happen. >> I had full faith in you.
>> Maybe in the last, 5-10 minutes, do you want to look at a couple of other non-chat examples? >> Yeah. >> If there's any questions feel free to pass them to me as well. >> I'll show you that Python one. That's right here. There's not as quite a few different apps in it.
I have an Azure Functions app and you can see a negotiate endpoint. The only difference is this is now written in Python, but it's basically the same thing. Let me close that. It looks exactly the same. >> People are logging in and sending messages. >> Oh, no. Well, at least I know you log in. >> I know. Yeah, it's all good.
>> I haven't built a moderation feature yet. I just have another one here, that instead of listening to HTTP, I'm listening to Event Hubs, which is like our high-scale events hub or event bus type of thing in Azure. The idea is that I'm simulating how we could potentially have maybe a Python script running on a bunch of Raspberry Pi's, that are just taking temperature readings or whatever kind of readings and just shooting that off into Event Hubs. Then on the other end of it, it's going to trigger this function and this function is again, not going to do a heck of a lot, it's just going to relay basically the payload from the events, which in this case is some fake temperature that it read from some fake device, and just relay it off to connect to clients.
>> Okay. >> But I want to use this to show that it's not just limited C-Sharp or JavaScript, it works in Python too. >> There's nothing that's fancy there.
It's just reading off of the event and then using JSON loads to convert the JSON into a Python dictionary, Python object, and then you're just returning that back using JSON dumps. >> Yeah. Really it's not doing much and this one line of code sends that message to everybody.
That's the function app, I don't think there's too much to show you there. I can skip the device simulator, it's just a fake script for me to just randomly generate temperature, a couple of times a second, and just shoot that down to Event Hubs. Then I'll show you the SignalR client, which is a Python script. It's 20 lines of code or something like that, but you can see very similar code that you saw, make a connection. Every time I see a new message, I am going to write it to my screen and I've got the library that I use, it's called terminal plot.
Basically, it looks like this, looks like it's still connected, so maybe it still works. Actually, I'm going to stop it for now, because I got to start everything up. I think I talked about everything. I'm going to go ahead and start my Azure Function app. Oh, no, something is using that port. Stop. I need to go stop this.
>> It's probably your last time demo. >> Let me stop this, stop that, go back over here. See if this works. >> I did notice that SignalR core is just available as a normal Python library so you just PIP and install. >> Yeah. >> Cool.
>> Someone else created this, so it's not an official Microsoft library, but it works pretty good from what I can tell. I don't know why I closed that, I meant to go over here. My function app is up, so now it's time to send some fake messages.
Just shooting some fake messages out. Then if I flip back over my function app, you can see that it's actually running. Then I can go off into my terminal now and I'll restart my client. You can see the little messages coming down here.
>> Okay. >> Yeah, it's painting it onto the screen in probably 1970s fashion. If you squint you might see a graph. >> No, I can start to see that that's coming together.
>> You have end-to-end, both the thing that's sending the messages, the function app itself, as well as the thing that's listening to SignalR messages, all working in Python. If that's your thing, you don't have to learn anything else. >> I dig it. Okay. Well, we'll get Jim Benedict into this since he's all about IoT and Python.
>> Actually shout out to, I don't know if you know Dave Glover, but he actually helped me with how to send messages from a Python script. So shout out to Dave. >> That's fantastic. If people wanted to learn more about SignalR or if they wanted to learn more about Azure Static Web Apps, where would they go to find said information? >> Actually this thing is really distracting me. I'm going to stop that. >> That's right. I switched back to
a dual-screen so you're all good. Okay. Good. I don't even have to show you anything. Microsoft Docs is a great place to start, especially to use SignalR Service with serverless. In the SignalR Service documentation, we have basically Azure Functions examples for every language that we support. If you want to learn more about how to connect to it and actually do stuff with it, SignalR has a bunch of docs on how you can use their different clients as well. But if you start off from the SignalR Service documentation, we should have links to everything, including some quickstarts that you can build your own chat app.
>> Actually I just found it in the background. This is pretty robust and I'm not saying that just because I work here, I'm looking through and there's a whole bunch of tutorials which I really like just because if I can just see the code a lot of times then I can figure the rest out from there. I really like the tutorials and I really also dig that there's a testing and debugging part as well. Not that anybody ever writes code that requires debugging, but just in case it happens >> Yeah.
>> That's fantastic. How about for learning more about Azure Static Web Apps? >> Again, Microsoft Docs is a great place to start, but we also have a bunch of courses or modules on Microsoft Learn. We also have a Microsoft Learn module on how to use SignalR Service with Azure Functions as well. With that one, you build this thing with Cosmos DB, like a pricing database, so you can see a bunch of prices. Then if you update something in Cosmos DB, it instantly gets reflected in the browser. So that's pretty cool. >> Look at that. Storing that into chat right now.
That's fantastic. Very cool. Where can people find you? >> I don't know. You want
my home address? Is that what you're looking for? >> I was assuming your Twitter handle, which is right up above your head. >> Is it over here? Yes, here. You can chat with me on Twitter, that's probably the easiest way to find me.
I'm sure there's different ways to GitHub, things like that. >> Too funny. I love it. At some point soon once COVID is no longer a thing, I'm going to have to get up to Vancouver, we'll have to go get dinner at Kissa Tanto, which is one of my favorite restaurants in the world. >> Nice, that's awesome. I never heard of that place. So you're going to show me around Vancouver. It's awesome.
>> It's spectacular. It's a Japanese-Italian fusion restaurant and it all comes together really well. >> Nice, I'm sold already. >> Beautiful. We will make that happen.
All right, Anthony, thank you so much for coming on, chatting about SignalR. You are going to be back again in a couple of three months to talk more about Azure Static Web Apps, which I'm super excited about because again, that's one of my favorite things. Again, best thing we've done since VS Code, although that little REST HTTP thing, that extension, that might be the new one. But anyway thanks again for coming on and showing us all about SignalR. >> Thanks for having me on. It's a lot of fun.
>> Beautiful. I love it. Thank you to everybody for tuning into Web Wednesday. Next week we're actually going to have Cassie Breviu on who's going to talk about Babylon.js
and how you can do cool MR things all inside of a browser with JavaScript. I'm super excited for that. Join next week and every week where we're chatting with smart people about web dev.
Thanks again for tuning in. Bye. I want that button, there we go.
2021-08-09 13:49