投稿時間:2021-11-22 09:16:32 RSSフィード2021-11-22 09:00 分まとめ(18件)

カテゴリー等 サイト名等 記事タイトル・トレンドワード等 リンクURL 頻出ワード・要約等/検索ボリューム 登録日
TECH Engadget Japanese ポータブル向けの2.5インチリムーバブルHDD「SQ2542」:スイートメモリーズ File076 https://japanese.engadget.com/sq-2542-pronote-230029406.html pronote 2021-11-21 23:00:29
IT ITmedia 総合記事一覧 [ITmedia News] Spotify、Premiumプランのアルバム再生は非シャッフルを初期設定に アデルのリクエストで https://www.itmedia.co.jp/news/articles/2111/22/news057.html itmedianewsspotify 2021-11-22 08:19:00
TECH Techable(テッカブル) MITが「どこかに埋もれているなくしもの」を見つけられるロボットを開発! https://techable.jp/archives/167117 開発 2021-11-21 23:00:18
js JavaScriptタグが付けられた新着投稿 - Qiita 【炎上、解消。】荒れたコメントや記事を見たくない人のためのアプリ https://qiita.com/KokumaruGarasu/items/a9e4b8c3b5ba5ebb42ec 】荒れたコメントや記事を見たくない人のためのアプリはじめに技術的な内容のみをご覧になりたい方はこちらからどうぞ以前の記事でも紹介したアプリ「ミュート」にYahooニュースなど各種サイトでのコメント欄非表示の機能を追加しました。 2021-11-22 08:08:13
js JavaScriptタグが付けられた新着投稿 - Qiita Express app.use 呼び出しタイミング https://qiita.com/jeronimo34/items/993cd6746e60ee4de4e1 2021-11-22 08:04:20
Program [全てのタグ]の新着質問一覧|teratail(テラテイル) enchant.js で進行方向が変わるときのコードの書き方がわかりません https://teratail.com/questions/370417?rss=all enchantjsで進行方向が変わるときのコードの書き方がわかりません前提・enchantjsでクマを上下左右に二秒ずつ歩かせるというものを作っております。 2021-11-22 08:35:35
Program [全てのタグ]の新着質問一覧|teratail(テラテイル) BootStrap StudioでLpを作る上での学習コスト https://teratail.com/questions/370416?rss=all BootStrapStudioでLpを作る上での学習コスト非エンジニアからの質問ですコーディング以前の質問で恐縮です。 2021-11-22 08:26:11
海外TECH DEV Community Shenanigans with Shaders https://dev.to/georgeoffley/shenanigans-with-shaders-3i97 Shenanigans with Shaders Table Of ContentsIntroductionShadersSetupShader CodeConclusionFor those of you who love rabbit holes learning graphics programming is a pretty deep one There s always some new thing to learn there s a bunch of different new languages and toolsets to know and on top of all that there s math Like anything else in programming you pick up momentum with each new thing you build so I found a tutorial and started making shaders I know very little about this However I m writing what I m learning so don t come for me if I m off on anything Shaders A shader is a program that runs on the GPU as part of the graphics pipeline We re going to focus primarily on shaders in Unity There are other ways to tackle this but Unity gives an easy setup to get started quickly For the context of Unity a shader is a small script containing logic and calculations for determining the colors of a pixel In Unity we create shader objects which act as wrappers for our shader program A shader object exists in a shader asset which is just the script we are writing Creating these in Unity allows for a great deal of freedom in what we make What we ll focus on is adding some basic functionality to a shader We ll be focusing on using ShaderLab to create shaders Setup The first thing to set yourself up making shaders in Unity is Unity So download it and create a new project I won t give a full rundown of Unity and the stuff you can do I leave that to better minds In the Hierarchy Window right click and scroll to D Object and click whichever object grabs your fancy I always pick sphere for testing stuff Now we have a D Mesh on the screen that we can begin adding things to it In the Project Window right click on the word Assets and create two new folders Materials and Shaders Double click into the Materials folder right click and Create is right at the top gt click Material Materials are similar to skins we can apply to D objects We will use this new material to add our new shader to the D Mesh After that drag our new material into the Scene Window where our sphere is and onto the sphere we made Now right click our Shaders folder scroll to Create gt Shader gt Standard Surface Shader Click the sphere in the Scene window to bring up the Inspector Window Finally drag the shader file over to the inspector window with our sphere covered in our new material We have just applied our shader to the materials You should see this in the Inspector Window Now go back to the Project window and double click our new Shader file Unity will launch an IDE for use to check out the code You can configure your choice of IDE I have VSCode configured Open the Shader file and let s check out the code I created some basic shader code you can use Shader Code Here is the complete minimal shader code It looks a bit much to anyone new to this including myself so let s take it a section at a time The first thing at the top starting with “Shader is the Shader Block This is used to define our Shader Object You can use this to define your properties create many shaders using the SubShader blocks assign custom options and assign a fallback shader object Here you can see the name of our shader and that it is in the “Custom directory Within the Shader block curly brackets we have our other sections The first is our Properties The properties box is where we define the properties for our materials A material property is what Unity stores along with our materials This allows for different configurations within Unity by creating things like sliders and inputs within the Inspector window for us to play around with We defined two properties the MainColor and the MainTexture Using square brackets I outlined which property was the default color and default texture We also defined the default values for these properties There s a bit to these values but suffice it to say both values are default white The second block is our SubShader this is where our shader logic goes You can define multiple sub shaders for many different uses For example depending on the graphics hardware you want to support you can make shaders for the various graphics APIs Within our block you can see some code for assigning tags assigning levels of detail LOD and the CGPROGRAM block I want to draw your attention to this section of the code First we define the data types for our inputs and outputs and create a function for us to serve the outputs into unity Our Input we set up as uv Maintex this allows for us to input a texture object Then we create a fixed variable for our Color attribute The o Albedo parameter is what is used to control the base color of the surface Here we are taking the values of our texture and multiplying them by our color input The code above gets you something similar to this I was proud of myself the first time I made this from memory Our coded shader lets us control the color of the material and add basic textures to it Working in graphics does not lead to instant gratification as anything you do requires a ton of setup However this and ShaderToy get you that dopamine hit Conclusion Above I went through some fundamentals of shaders in Unity I skipped over a ton of information as I m still learning a lot and a full informed explainer would be twenty pages long There is a lot to programming graphics and shaders specifically I suggest you check out stuff like Team Dogpit s shader tutorial for a way better deep dive I m excited to dig into this world I want to learn to create some of the incredible stories I see in animation and any first step is a step in the right direction Thanks for reading George 2021-11-21 23:22:52
海外TECH DEV Community Oops, I Did It Again...I Made A Rust Web API And It Was Not That Difficult https://dev.to/deciduously/oops-i-did-it-againi-made-a-rust-web-api-and-it-was-not-that-difficult-3kk8 Oops I Did It Again I Made A Rust Web API And It Was Not That DifficultOver two years ago gulp I posted a walkthrough of my Rust implementation of todo mvp by gypsydave demonstrating how to build a simple Rust API without a framework The core functionality was built using hyper a lower level HTTP library instead of a full blown framework It turns out I wrote that post about six months too early I published it in May and in November Rust released containing async await syntax Womp womp My intent here was to simply upgrade the existing application to use the new syntax where applicable and call it a day But you know that thing that happens when you go back and review code you wrote years ago Yeah that thing happened We re starting from scratch What s NewOur result functions almost identically to the implementation in the previous post so some of this code will look very similar Here s a quick overview of the new stuff you ll find in this post not present in the previous version anyhow Error handling for humans async await New syntax for expressing asynchronous computation like a webserver catch unwind A panicking thread shouldn t crash your whole server Gracefully catch the panic and keep on servin compression Every response will be DEFLATE compressed simply because we can state management Instead of a global variable we ll use protocol extensions to access the app state tracing The log crate is old news All the cool kids use tracing now unit testing We didn t have any last time tsk tsk Learn how to write async unit tests for your handlers SetupTo follow along you ll need a stable Rust toolchain See the install page for instructions to install rustup for your platform You should prefer this method to your distribution s package manager If you re a NixOS freak I recommend fenix Once your environment is set up start a new project and make sure you can build it cargo new simple todo Created binary application simple todo package cd simple todo cargo run Compiling simple todo v home deciduously code simple todo Finished dev unoptimized debuginfo target s in s Running target debug simple todoHello world Open up your Cargo toml and make it look like this package authors Cool Person lt cool person yourcoolsite neato gt edition rustc version name simple todo version dependencies anyhow backtrace clap version beta features color flate futures hyper version features full lazy static serde version features derive serde json tracing tracing subscriber version features env filter tera tokio version features full uuid version features serde v dev dependencies pretty assertions select There are some new elements here already up in the package section Rust was recently released and along with it the rust version metadata key allowing you to specify the Minimum Supported Rust Version MSRV directly in the package This post is only concerned with Rust and will use assets identical to the last post Create a folder called templates at the project s top level and place this index html inside You will also need to create a directory at src resource and fill it with these files There is a stylesheet and a handful of SVG files Your structure should look like this tree ├ーCargo lock├ーCargo toml├ーsrc│├ーmain rs│└ーresource│├ーcheck svg│├ーplus svg│├ーtick png│├ーtodo css│├ーtrashcan svg│└ーx svg└ーtemplates └ーindex htmlGood to go EntrypointThis whole app will live in src main rs Start off by adding the imports use anyhow Result use backtrace Backtrace use clap Parser use flate write ZlibEncoder Compression use futures future FutureExt Future use hyper http use lazy static lazy static use serde Serialize use std cell RefCell convert Infallible io Write panic AssertUnwindSafe path PathBuf sync Arc RwLock use tera Tera use uuid Uuid It s nice to allow the user to specify where to run their app The clap library provides a convenient way to specify command line arguments in a struct This feature is still in beta but will stabilize soon We can create a struct and use the Parser feature to generate the options derive Parser clap version concat env CARGO PKG VERSION about Serve a TODO list application struct Args clap short long about Address to bind the server to env default value address String clap short long about Port to listen on env default value port u When run without any arguments the server will bind to a reasonable default This allows users to either use the ADDRESS and PORT environment variables or a address and p port command line arguments It also provides a nice help implementation simple todo Serve a TODO list application USAGE todo mvp rust OPTIONS OPTIONS a address lt ADDRESS gt Address to bind the server to env ADDRESS default h help Print help information p port lt PORT gt Port to listen on env PORT default V version Print version informationOur main function will just parse these arguments and pass them off to our app routine fn main gt Result lt gt let args Args parse app args Ok I ve brought anyhow Result into scope making error handling super easy to use We don t need to specify all our Error types It can automatically convert any errors that implement std error Error which should be all of them If an error propagates all the way up to main we ll get all the info it s captured printed to stdout The app function is our real entrypoint tokio main async fn app args Args gt Result lt gt tracing subscriber fmt init let addr std net SocketAddr new args address parse args port let todos Todos new let context Arc new RwLock new todos serve addr context handle await Ok This function is tagged with tokio main meaning it will execute an async runtime All the functions we re using now can be marked async meaning we can await the result Under the hood Rust converts these functions into constructs that can either be Ready or Waiting You can call the poll method on a future which just asks are you ready or are you waiting If the future is ready to resolve it will pass up the response and if it s waiting it will just respond with Pending It can return a wake callback letting the caller know there s a value When wake is executed the caller will know to poll this future again resolving it to a value This all involved a lot of ceremony This async await syntax abstracts these concepts for us We just write functions like normal except we mark them async and when control flow hits a point where we need to wait for a result to resolve we can use await If these are used within an executor like tokio main the runtime will cover all the details This makes our types easier to reason about and our code much more straightforward to write This top level function reads our argument struct to build the SocketAddr to bind to starts up the logging system with tracing subscriber and builds our state management Then we call the serve async function and await on the result This executor will run forever until the user kills the process and can handle multiple concurrent connections for us seamlessly For a sneak preview this is the signature of serve async fn serve lt C H F gt addr std net SocketAddr context Arc lt C gt handler H gt hyper Result lt gt where C static Send Sync H static Fn Request gt F Send Sync F Future lt Output Response gt Send It requires we pass an address then an Arc lt C gt That C type is our app state and for this to work it must implement the Send and Sync traits Send means the value can be sent to another thread and Sync means it can be shared between threads simultaneously In our case we don t need to think too hard about this We re using an Arc lt RwLock lt T gt gt to allow mutation to provide a type that can be accessed from multiple threads and safely mutated as needed As long as each thread grabs the proper lock we don t need to worry about concurrent threads clobbering each other Only one thread will be able to write to this type at a time so every new reader will always have the correct data Finally we need to add a handler with type H These types start to peel back a little of what async is doing for us Stripping out the Send Sync trait bounds this function satisfies the trait bound Fn Request gt Future lt Output Response gt Because we re in an async environment we can just write async fn handle request Request gt Response it s an asynchronous function from a request to a response Sounds like a web server to me Using Rust s async await we get to simply write what we mean We ll come back to the handler shortly first we have a little bit of setup to take care of TemplatesThis application only consists of a single page that will be refreshed whenever the state changes We placed markup at templates index html an HTML file using Jinja style templating We ll use Tera to handle this in Rust The templates need to be compiled before use but this only needs to happen once We can use lazy static to ensure this compilation happens the first time the templates are accessed and then reuse the compiled result for all subsequent access lazy static pub static ref TERA Tera match Tera new templates Ok t gt t Err e gt eprintln Unable to parse templates e std process exit Now we can use the TERA global If Tera could not compile the templates for any reason the process will exit here and display the error Our server only works if this step completes successfully StateNext we need to define the app state The application revolves around a Todo type with a name an ID and a boolean tracking whether it s been completed derive Debug Serialize pub struct Todo done bool name String id Uuid impl Todo fn new name amp str gt Self Self done false name String from name id Uuid new v We just need to provide a string name like Todos new Task and this type will generate a new unique ID and set it to incomplete Storage is pretty simple derive Debug Default struct Todos Vec lt Todo gt We need methods to add new todos remove existing todos and toggle the done boolean impl Todos pub fn new gt Self Self default pub fn push amp mut self todo Todo self push todo pub fn remove amp mut self id Uuid gt Option lt Todo gt let mut idx self len for i todo in self iter enumerate if todo id id idx i if idx lt self len let ret self remove idx Some ret else None pub fn todos amp self gt amp Todo amp self pub fn toggle amp mut self id Uuid for todo in amp mut self if todo id id todo done todo done Notably we don t have to write any unique code to make this thread safe We can write it exactly as we would in a single threaded synchronous context and trust that Rust won t let us mutably access this unsafely This is what got instantiated up in app with these lines let todos Todos new let context Arc new RwLock new todos Wrapping this all in an Arc means that any thread accessing this value can get their own reference to it and the RwLock will allow multiple concurrent readers or exactly one writer at a time When the lock is released the following thread will be able to take control HandlerWe re finally ready to take a look at the handler Per the signature up above we know we need a function with the following signature async fn handle request Request gt Response Each time our web server receives an HTTP request it will call this function to produce a Response to send back First add type aliases for the request and response type Request http Request lt hyper Body gt type Response http Response lt hyper Body gt The hyper crate defines all the types we need In both cases the request and response will carry a hyper Body Every single handler will use this type signature so defining these aliases saves us a lot of typing The request contains information about how it was sent We can use Rust s match construct to read both the incoming URI and HTTP method to correctly dispatch a response Here s the whole body async fn handle request Request gt Response pattern match for both the method and the path of the request match request method request uri path GET handlers Index page handler amp hyper Method GET amp hyper Method GET index html gt index request await Style handler amp hyper Method GET static todo css gt stylesheet await Image handler amp hyper Method GET path str gt image path str await POST handlers amp hyper Method POST done gt toggle todo handler request await amp hyper Method POST not done gt toggle todo handler request await amp hyper Method POST delete gt remove todo handler request await amp hyper Method POST gt add todo handler request await Anything else handler gt four oh four await Each match arm will match with a specific combination of HTTP verb and path For example GET static todo css will properly dispatch the stylesheet handler but POST static todo css is not supported and will fall through to four oh four Each of these handlers is itself an async function but we don t want to return up to the caller until they ve been polled as ready and return an actual Response Remember Rust is doing this for us when we write async fn gt Response we actually get a Fn gt impl Future lt Output Response gt We can t use that return type until the future resolves That s what the await syntax signifies Once the future is ready we ll use the resulting Response output but not before The most straightforward handler is four oh four async fn four oh four gt Response html str handler lt h gt NOT FOUND lt h gt http StatusCode NOT FOUND await This response doesn t depend on the request the request didn t make any sense to us after all There s no input parameter but like all handlers it produces a Response Because all of our routes need to build responses I pulled this logic out into a series of building block functions Response BuildersMost of our Response building shares a lot of logic We usually send back some form of string and we want to attach a content type and a status code Because we care about our user s bandwidth usage we also want to compress our responses ensuring as little as possible is sent over the wire The most common case is a successful response containing HTML async fn ok html handler html amp str gt Response html str handler html http StatusCode OK await This in turn calls the HTML string handler async fn html str handler html amp str status code http StatusCode gt Response string handler html text html status code await Our four oh four handler used this directly to include a different status code Ultimately though it s all just strings async fn string handler body amp str content type amp str status code http StatusCode gt Response bytes handler body as bytes content type status code await async fn ok string handler body amp str content type amp str gt Response string handler body content type hyper StatusCode OK await These helpers allow for other content types as long as the body is still passed as a string This covers all the body types we need for this application At the bottom we get to bytes handler async fn bytes handler body amp u content type amp str status code http StatusCode gt Response let mut encoder ZlibEncoder new Vec new Compression default encoder write all body unwrap let compressed encoder finish unwrap hyper Response builder status status code header hyper header CONTENT TYPE content type header hyper header CONTENT ENCODING deflate body hyper Body from compressed unwrap This function takes a byte slice amp u and DEFLATE compresses it It adds the proper Content Encoding header so that any connected client can uncompress the payload before presenting it back to the user This is a rapid operation and the smaller your payloads the better Every response that contains a body will eventually pass through this function before bubbling back up to the top level handle function and back to the client There s one more response type for this application and this doesn t use a body at all Whenever our app state changes we will use the HTTP status code to trigger the client to redirect back to the index Every time the index is rendered it reads the current app state meaning any mutation executed in the handler will be automatically reflected on the refresh This function calls Response builder directly async fn redirect home gt Response hyper Response builder status hyper StatusCode SEE OTHER header hyper header LOCATION body hyper Body from unwrap Main pageNow we have everything we need to render the app Our index function is the first handler that requires state async fn index request Request gt Response Set up index page template rendering context let mut tera ctx tera Context new let todos ctx Arc lt RwLock lt Todos gt gt Arc clone request extensions get unwrap let lock todos ctx read unwrap let todos lock todos let len todos len tera ctx insert todos todos tera ctx insert todosLen amp len let html TERA render index html amp tera ctx unwrap to string ok html handler amp html await In the previous iteration of this app the Todos struct was instantiated alongside our TERA templates in a global static variable That s kind of gross A better solution is to thread it through to our handler using the Request itself We ll look at the implementation lower down but by the time we get here there s a fresh Arc containing the context ready to be read We can use request extensions get and Arc clone to grab our very own reference to the app state to use for building this response The request extensions use the type of what s stored for access so we need to explicitly add the type of todos ctx to indicate what we re looking for Next we build the index page using the current state of the app This handler won t perform any mutation so we can use todos ctx read By introducing a child scope we ensure our read lock gets dropped when we re done with it allowing any writers waiting for access to grab their own locks If we needed to wait no problem We re in an async function the caller can poll us any time and we ll just return Pending until we re ready to go Nice and neat Once we ve received our handle to the app state we can pass it through to Tera TERA render will return an HTML string with all template values resolved using our app state Then we can use our trusty ok html handler response builder to tag it with a proper content type and status code and compress the result before returning to the caller The index html template will request a style sheet when it loads from static todo css That s a pretty simple handler async fn stylesheet gt Response let body include str resource todo css ok string handler body text css await The include str macro actually bundles the string content directly in your compiled binary These files need to be present at compile time but do not need to be distributed in production The compiled binary already includes everything it needs SVGAll the image assets in this application are SVG which is represented as XML This means we just need to read these strings and pass the proper content type async fn image path str amp str gt Response let path buf PathBuf from path str let file name path buf file name unwrap to str unwrap let ext match path buf extension Some e gt e to str unwrap None gt return four oh four await match ext svg gt build the response let body match file name check svg gt include str resource check svg plus svg gt include str resource plus svg trashcan svg gt include str resource trashcan svg x svg gt include str resource x svg gt ok string handler body image svg xml await gt four oh four await I just used a catch all any GET request that s not for the index or the stylesheet is assumed to be for an image At the top there s a little extra logic to make sure we re looking for an image file If there s no extension i e nonsense this handler will dispatch a four oh four Otherwise we press forward and try to find the actual SVG file If we succeed we just pass the string back and if not we also four oh four State HandlersThe remaining handlers are involved with mutating the state All of them will pass a request body with an item For a new todo it will be item Task and for toggling or removing it will hold the id item efa d f a eed In either case we just need to extract the value after the equals sign async fn extract payload request Request gt String let body request into body let bytes buf hyper body to bytes body await unwrap let str body String from utf bytes buf to vec unwrap let words Vec lt amp str gt str body split collect words to owned The body may come in chunks so we use hyper body to bytes to produce a single Bytes value with everything concatenated We can then convert the bytes to a UTF string and split on the to grab the actual payload All of our state mutation handlers call this function on the incoming request async fn add todo handler request Request gt Response let todos ctx Arc lt RwLock lt Todos gt gt Arc clone request extensions get unwrap let payload extract payload request await let mut lock todos ctx write unwrap lock push Todo new amp payload redirect home await async fn remove todo handler request Request gt Response let todos ctx Arc lt RwLock lt Todos gt gt Arc clone request extensions get unwrap let payload extract payload request await let mut lock todos ctx write unwrap lock remove Uuid parse str amp payload unwrap redirect home await async fn toggle todo handler request Request gt Response let todos ctx Arc lt RwLock lt Todos gt gt Arc clone request extensions get unwrap let payload extract payload request await let mut lock todos ctx write unwrap lock toggle Uuid parse str amp payload unwrap redirect home await Each handler grabs its own unique reference to the app state then extracts the payload Like we did in index we open a new scope to interact with the RwLock mutex and in this case we use todos ctx write to request a mutable lock This blocks all other threads until the mutation is complete Then we just redirect home This prompts the client to send a GET request which leads our to level handler to call index which reads the newly mutated app state to build the page Groovy That s a full fledged TODO app ServeThere s one missing piece We defined our handle function but we haven t talked about serve beyond the type signature This one is pretty beefy async fn serve lt C H F gt addr std net SocketAddr context Arc lt C gt handler H gt hyper Result lt gt where C static Send Sync H static Fn Request gt F Send Sync F Future lt Output Response gt Send Create a task local that will store the panic message and backtrace if a panic occurs tokio task local static PANIC MESSAGE AND BACKTRACE RefCell lt Option lt String Backtrace gt gt async fn service lt C H F gt handler Arc lt H gt context Arc lt C gt mut request http Request lt hyper Body gt gt Result lt http Response lt hyper Body gt Infallible gt where C Send Sync static H Fn http Request lt hyper Body gt gt F Send Sync static F Future lt Output http Response lt hyper Body gt gt Send let method request method clone let path request uri path and query unwrap path to owned tracing info path path method method request request extensions mut insert context let result AssertUnwindSafe handler request catch unwind await let start std time SystemTime now let response result unwrap or else let body PANIC MESSAGE AND BACKTRACE with panic message and backtrace let panic message and backtrace panic message and backtrace borrow let message backtrace panic message and backtrace as ref unwrap tracing error method method path path backtrace backtrace format n message backtrace http Response builder status http StatusCode INTERNAL SERVER ERROR body hyper Body from body unwrap tracing info Response generated in μs start elapsed unwrap or default as micros Ok response Install a panic hook that will record the panic message and backtrace if a panic occurs let hook std panic take hook std panic set hook Box new panic info let value panic info to string Backtrace new PANIC MESSAGE AND BACKTRACE with panic message and backtrace panic message and backtrace borrow mut replace value Wrap the request handler and context with Arc to allow sharing a reference to it with each task let handler Arc new handler let service hyper service make service fn let handler handler clone let context context clone async move Ok lt Infallible gt hyper service service fn move request let handler handler clone let context context clone PANIC MESSAGE AND BACKTRACE scope RefCell new None async move service handler context request await let server hyper server Server try bind amp addr tracing info serving at addr server serve service await std panic set hook hook Ok I know I know There s a lot here The meat of this function happens right at the end let server hyper server Server try bind amp addr tracing info serving at addr server serve service await We build a hyper Server bind it to the address we constructed from the Args struct and serve this service thing The service is built right above that let handler Arc new handler let service hyper service make service fn let handler handler clone let context context clone async move Ok lt Infallible gt hyper service service fn move request let handler handler clone let context context clone PANIC MESSAGE AND BACKTRACE scope RefCell new None async move service handler context request await We also wrap the handler function in an Arc Our context is already wrapped so we clone both to get a local reference within this closure This allows the executor to spin up multiple concurrent versions of our handler service that all have access to the same state and logic The beefy stuff happens in this service closure above This is where we take an incoming request and match it up with our handler and context A new instance is executed for each incoming request and all this ceremony allows this to happen without interfering with other simultaneous requests For the most part you can just copy this all as is and not worry about it but I ll explain some of the essential pieces For one this is where we add our context to the request request extensions mut insert context When we call request extensions get in our mutating handlers we re pulling out the context added at this stage There s also some logging added We trace the request s specifics and start a timer that reports how long the request took To see this logging in action set the environment variable RUST LOG info when executing the server process Catching PanicsThe most exciting part to me at least is the panic handler We always want our requests to succeed However there are situations where we may encounter a panic This will cause the entire Rust program to crash and print out a stack trace in normal usage However this is a web service A panic situation in one request handling process shouldn t prevent other requests from executing We don t want the whole server to crash we still want to handle these situations gracefully We can intercept the normal panic behavior and instead simply produce a different response containing the details At the top we create a task local storage location tokio task local static PANIC MESSAGE AND BACKTRACE RefCell lt Option lt String Backtrace gt gt This is local to just the currently executing Tokio task not the whole program Then we replace the default panic logic with our own let hook std panic take hook std panic set hook Box new panic info let value panic info to string Backtrace new PANIC MESSAGE AND BACKTRACE with panic message and backtrace panic message and backtrace borrow mut replace value std panic set hook hook First we grab the existing hook and store it to the hook variable Then we overwrite our own At the end of the function we make sure to reset the global panic hook back to what it was If the thread panics inside this function for example one of our unwrap statements encounter a non success we ll store the panic message and backtrace to this task local location However we will not abort the process Up above in the service location we can catch this happening let result AssertUnwindSafe handler request catch unwind await We attempt to build the response but this result will not be a success if anything happens If it was a success great we pass it back up However if we find an error value here we can dispatch different logic let response result unwrap or else let body PANIC MESSAGE AND BACKTRACE with panic message and backtrace let panic message and backtrace panic message and backtrace borrow let message backtrace panic message and backtrace as ref unwrap tracing error method method path path backtrace backtrace format n message backtrace http Response builder status http StatusCode INTERNAL SERVER ERROR body hyper Body from body unwrap For most requests that result unwrap went fine and we just stored our response to Response However if it was an error we can read the result of the panic from this task local area We emit an error trace on the server side and then build a new response with status code INTERNAL SERVER EROR This response includes the full backtrace as the body This means our server can keep handling other requests without interruption but the specific client that caused the panic gets a complete log of the problem and our server has logged the backtrace as well We can diagnose the issue without losing uptime for any other client Now no matter what happened while processing the request we ve stored a valid hyper Response to this response value and we can pass that back to the caller even if something catastrophic occurs We can safely use Ok lt Infallible gt signifying that there is no possible way for control to fail to hit this point Our server will always generate a response and continue even if something terrible happens Good stuff TestsFinally we want to ensure we can automate tests I ll just demonstrate a test of our handler which includes all the pieces needed to build a robust test suite cfg test mod test use super use flate write ZlibDecoder use pretty assertions assert eq use select document Document predicate Name tokio test async fn test four oh four let mut request hyper Request builder method http Method GET uri nonsense body hyper Body empty unwrap let context Arc new RwLock new Todos new request extensions mut insert Arc clone amp context let response handle request await assert eq response status http status StatusCode NOT FOUND let body hyper body to bytes response into body await unwrap let mut decoder ZlibDecoder new Vec new decoder write all amp body unwrap let uncompressed decoder finish unwrap let result String from utf uncompressed unwrap let document Document from result as str let message document find Name h next unwrap text assert eq message NOT FOUND to owned Tokio provides a tokio test macro for building async tests We can use hyper Request to construct a request and build our context the same way we did in the server Because our handler is just a function from a Request to a Response we can test it very simply let response handle request await We first assert the status code matches what we expect then we have to decode the body We use the ZlibDecoder to read the response body and decompress it back to a string Once we have our string response we can use the select rs library to ensure the structure matches our intent In this case we are asserting we ve received an h element with a text body matching the string NOT FOUND FinThis implementation is an improvement over the previous in several fundamental ways The async await syntax allows us to write code closely matching our intent without getting bogged down with Box es and Future s We avoid polluting the global scope and use the Request itself to handle concurrent access to the app state and even catastrophic request handling errors gracefully without affecting other clients Our handler is straightforward to test This application provides a solid performant base for building more complex applications and keeps the dependencies and therefore compile times and bundle sizes to a minimum While there are many different frameworks for building web applications in Rust it s worth asking yourself whether you actually need that level of abstraction For many web service needs putting the building blocks together yourself isn t much more complicated and you retain control over how you build your application If we want to deconstruct the request URI we can do that already If we return JSON we just need to create a struct that implements serde Serialize The conclusion here is the same as before when the end goal is simple enough why not use simple tools Cover photo by Danny Howe on Unsplash 2021-11-21 23:02:27
金融 日本銀行:RSS FSBレポ統計の日本分集計結果 http://www.boj.or.jp/statistics/bis/repo/index.htm 集計 2021-11-22 08:50:00
海外ニュース Japan Times latest articles Chinese tennis star Peng Shuai reappears, speaking by video with IOC president https://www.japantimes.co.jp/news/2021/11/22/asia-pacific/peng-shuai-ioc-china/ Chinese tennis star Peng Shuai reappears speaking by video with IOC presidentPeng told IOC chief Thomas Bach that she is safe and well living at her home in Beijing but would like to have her privacy 2021-11-22 08:25:25
ニュース BBC News - Home Justin Bieber urged to cancel Saudi show by Khashoggi's fiancee https://www.bbc.co.uk/news/world-middle-east-59369676?at_medium=RSS&at_campaign=KARANGA arabia 2021-11-21 23:42:13
ニュース BBC News - Home The Papers: 'Rage across Europe', and Tory social care warnings https://www.bbc.co.uk/news/blogs-the-papers-59369465?at_medium=RSS&at_campaign=KARANGA front 2021-11-21 23:51:38
LifeHuck ライフハッカー[日本版] 経済的弱者を食い物にする「マイクロワーク」の正体とは https://www.lifehacker.jp/2021/11/246004how-microwork-preys-on-the-desperate-and-other-reasons.html 落とし穴 2021-11-22 08:30:00
北海道 北海道新聞 31歳で結婚、寿命は79歳 Z世代、人生の理想を調査 https://www.hokkaido-np.co.jp/article/614258/ 調査 2021-11-22 08:18:12
北海道 北海道新聞 F1、フェルスタッペンが2位 角田13位、第20戦 https://www.hokkaido-np.co.jp/article/614278/ 角田 2021-11-22 08:05:00
北海道 北海道新聞 【道スポ】稲葉GM、小学生を指導 札幌の屋内練習場で野球教室 https://www.hokkaido-np.co.jp/article/614277/ 日本ハム 2021-11-22 08:03:00
ビジネス 東洋経済オンライン 台湾からの「視線」に日本が注意するべき理由 「コロナ対応」で自己肯定感を強める「台湾」 | 中国・台湾 | 東洋経済オンライン https://toyokeizai.net/articles/-/468578?utm_source=rss&utm_medium=http&utm_campaign=link_back 安全保障 2021-11-22 08:30:00

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)