From 0044f114b87792cbc6dd70bad3562d53a61f5b23 Mon Sep 17 00:00:00 2001 From: Sunghoon Kang Date: Thu, 12 Sep 2024 17:08:58 +0900 Subject: [PATCH 1/3] fix: use `io.Copy` instead of `ReadLine` for http streaming Current behavior may cause unintended response stream since it reads line and concatenate them with newline. This commit fixes the issue by using `io.Copy` to stream response body instead of using `ReadLine`. Signed-off-by: Sunghoon Kang --- api/proto/testv1/test.proto | 9 + internal/assets/assets.go | 8 + internal/assets/large_file.txt | 211 +++++++++++++++++++++ internal/test/gen/testv1/test.gw.client.go | 6 + internal/test/gen/testv1/test.pb.go | 202 +++++++++++++------- internal/test/gen/testv1/test.pb.gw.go | 50 +++++ internal/test/gen/testv1/test_grpc.pb.go | 64 +++++++ internal/test/server/server.go | 13 ++ pkg/grpc/gateway/request.go | 35 +--- pkg/grpc/gateway/request_test.go | 30 +++ 10 files changed, 532 insertions(+), 96 deletions(-) create mode 100644 internal/assets/assets.go create mode 100644 internal/assets/large_file.txt diff --git a/api/proto/testv1/test.proto b/api/proto/testv1/test.proto index 608fef8..c829fc8 100644 --- a/api/proto/testv1/test.proto +++ b/api/proto/testv1/test.proto @@ -27,6 +27,11 @@ service TestService { get: "/download-invitations" }; } + rpc DownloadLargeFile(DownloadLargeFileRequest) returns (stream google.api.HttpBody) { + option (google.api.http) = { + get: "/download-large-file" + }; + } } message InvitationMetadata { @@ -78,3 +83,7 @@ message TrackInvitationResponse { message DownloadInvitationsRequest { optional EventType type = 1; } + +message DownloadLargeFileRequest { + // Explicitly empty +} diff --git a/internal/assets/assets.go b/internal/assets/assets.go new file mode 100644 index 0000000..71c0335 --- /dev/null +++ b/internal/assets/assets.go @@ -0,0 +1,8 @@ +package assets + +import _ "embed" + +var ( + //go:embed large_file.txt + LargeFile string +) diff --git a/internal/assets/large_file.txt b/internal/assets/large_file.txt new file mode 100644 index 0000000..6535391 --- /dev/null +++ b/internal/assets/large_file.txt @@ -0,0 +1,211 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel pulvinar turpis. Curabitur egestas nisi tellus, et semper nisl vestibulum a. Donec et tortor lorem. Suspendisse ac erat eget libero bibendum gravida id eget ante. Sed sit amet lacus id ipsum semper iaculis. Etiam pretium hendrerit ullamcorper. Sed cursus quam sed laoreet elementum. + +Quisque pulvinar pulvinar varius. Integer in porta turpis, non luctus libero. Aliquam erat volutpat. Donec cursus venenatis sapien vitae pretium. Vivamus eu massa vel ex tincidunt viverra eget ac eros. Aliquam vitae urna lobortis, elementum nibh eget, molestie enim. Phasellus sagittis aliquet posuere. + +Integer tincidunt eget lorem non blandit. Nulla luctus lacinia velit. Ut ut lectus aliquet, ultricies nulla ut, molestie justo. Pellentesque tristique viverra orci, sed vehicula massa rutrum a. Aenean efficitur justo sit amet blandit suscipit. Curabitur semper leo erat, nec varius orci fermentum sit amet. Pellentesque convallis felis euismod fermentum lacinia. Phasellus massa ipsum, ultrices nec venenatis et, pellentesque quis diam. Proin tincidunt, neque in pharetra convallis, turpis velit dapibus magna, a feugiat nulla est sed augue. In et augue at purus condimentum pharetra non quis erat. Morbi posuere mauris vitae lobortis ornare. Mauris fermentum felis ut dapibus condimentum. Suspendisse ornare urna eget dui blandit, in sagittis massa viverra. + +Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed quis consectetur nunc, eget eleifend ante. Phasellus egestas nunc non arcu luctus pharetra. Nam accumsan massa dui, a iaculis dolor bibendum facilisis. Ut quis enim eget quam pharetra congue. Cras lectus nisl, pellentesque quis enim sit amet, accumsan dignissim quam. Nunc risus leo, eleifend eu ligula vel, feugiat maximus justo. Nam blandit, orci semper sollicitudin tincidunt, nibh nunc consectetur eros, id cursus diam magna eu orci. Phasellus ut finibus risus, ut scelerisque odio. Etiam magna diam, efficitur convallis turpis luctus, aliquam aliquet lectus. Suspendisse vitae diam in libero malesuada luctus at eu nibh. Etiam magna dolor, molestie vel nisi a, interdum scelerisque enim. Curabitur nec nisl feugiat, fermentum turpis id, viverra erat. Praesent eleifend sem sit amet erat vulputate, ut ultricies tortor viverra. Aenean magna magna, lacinia nec lectus sit amet, ullamcorper vehicula odio. Donec sit amet velit sit amet erat rhoncus pellentesque. + +Nulla vitae finibus sapien. Nulla non orci non lorem ullamcorper lacinia. In vitae orci facilisis, convallis est id, tincidunt tellus. Mauris arcu tellus, consequat sed enim eget, pharetra porta nibh. Vestibulum ac accumsan velit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras ac magna tempor, vehicula dui vitae, vehicula massa. Mauris nec enim lacinia, convallis orci vel, rhoncus tortor. Sed condimentum mauris nec nulla tempus ultricies. Nullam at dolor at massa malesuada venenatis id ut erat. Aliquam placerat molestie velit, eu accumsan risus euismod sed. Sed eget nulla sed risus facilisis condimentum eu at nisi. + +Nunc nec sem at neque molestie dictum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur sit amet auctor velit. Fusce eu velit id lectus scelerisque luctus vel ut lectus. Quisque eleifend pharetra placerat. Quisque placerat orci id feugiat fringilla. Maecenas eu iaculis purus. Donec vitae ipsum diam. Aenean rhoncus enim quis risus rutrum, a auctor massa condimentum. Morbi nulla dolor, tincidunt ullamcorper felis quis, auctor facilisis purus. Cras rhoncus iaculis elit, a fringilla sapien rutrum a. Phasellus iaculis ipsum enim, vel malesuada turpis sollicitudin id. + +In hac habitasse platea dictumst. Duis tincidunt vehicula nunc, non fringilla lacus vestibulum vitae. Cras vulputate gravida libero vel condimentum. Aenean blandit odio sapien, non vehicula justo congue vel. Morbi tincidunt sapien nec porta interdum. Cras eget fermentum magna. Aenean dolor risus, cursus vitae erat quis, blandit ornare eros. Cras dictum finibus est, sit amet pulvinar magna finibus in. Aenean gravida urna semper, pretium nulla non, condimentum nunc. + +Pellentesque scelerisque nisl metus, vel scelerisque massa eleifend vitae. Etiam tristique gravida ipsum eget tempus. Quisque pellentesque quam urna, in commodo risus tempus sed. Curabitur accumsan diam et mollis feugiat. Integer ut libero urna. Nam consequat libero est. Maecenas congue tortor in neque volutpat viverra. Donec ut lacus metus. Cras tempor arcu sed molestie ultricies. Cras fringilla erat in auctor tempus. + +Integer blandit finibus lacus, at blandit odio placerat a. Phasellus viverra vel nulla ut interdum. Donec at tortor ligula. Integer rhoncus risus eu libero porta, at iaculis nunc rutrum. Mauris iaculis est eu massa finibus finibus. Aliquam erat volutpat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In hac habitasse platea dictumst. Suspendisse potenti. In ut quam ac dolor efficitur posuere nec et tellus. Phasellus tincidunt elementum urna id varius. Curabitur porta faucibus eleifend. + +Proin mattis, massa eleifend ullamcorper tristique, massa nunc vulputate sem, eu accumsan sem nisl quis nisl. Morbi cursus in nisl at pulvinar. Sed tincidunt odio vitae magna tempor ullamcorper. Donec in velit eget libero viverra tincidunt. Vestibulum sit amet turpis at quam molestie semper sed nec nulla. Vestibulum mollis tempus sem, id volutpat nibh luctus sit amet. Sed nec tempor nulla. Suspendisse elementum dolor quis massa maximus dignissim. Pellentesque commodo porta nulla ut molestie. + +Aliquam eleifend lectus nec magna volutpat aliquam. Vestibulum accumsan vel ligula blandit venenatis. Nullam condimentum lacus in ex lobortis pharetra. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Phasellus sit amet felis rutrum, gravida nisl cursus, tincidunt massa. Integer pharetra enim vel elit pulvinar, a sollicitudin ligula suscipit. Fusce a libero lorem. Morbi suscipit neque et nisl faucibus, id fermentum lacus pellentesque. Vivamus facilisis tempus felis sed scelerisque. Duis scelerisque nisi sed justo bibendum, sed convallis lacus bibendum. Cras facilisis massa eleifend, ullamcorper nunc ut, auctor neque. Aenean ac accumsan arcu, in auctor dolor. Ut venenatis varius nulla, a vehicula sapien egestas dapibus. Proin eu erat lectus. Nunc sodales et orci ullamcorper laoreet. + +Duis ac lacinia lorem. Maecenas eget sollicitudin mi. Proin eget neque ornare turpis consectetur tincidunt. Pellentesque ac malesuada augue. Etiam condimentum lacus sit amet turpis lobortis porta. Praesent eget mi vitae ipsum rhoncus finibus id non turpis. Proin at fermentum justo, eu hendrerit odio. Vivamus lacus lectus, hendrerit non tincidunt imperdiet, egestas sit amet lectus. Vestibulum ut lorem ut massa volutpat lobortis eget sit amet odio. Vestibulum eget tincidunt nibh. Suspendisse consectetur tellus vitae nulla varius aliquet. Quisque rhoncus ligula lobortis congue dignissim. + +Nullam vitae fringilla enim, sit amet rutrum nibh. Suspendisse aliquet elementum leo et finibus. Quisque gravida ac metus nec consequat. Aliquam massa mauris, consectetur eget ipsum a, sagittis pharetra metus. Vivamus nec ornare leo, non placerat purus. Nulla eleifend facilisis mi, at commodo mi rutrum volutpat. Fusce vestibulum, magna et lacinia bibendum, neque velit euismod ipsum, sed ultricies nulla sem ac massa. Mauris facilisis ac dui eu ultrices. Cras ultrices, dolor in consequat consequat, ex lorem varius diam, non iaculis lorem orci eu turpis. + +Phasellus elementum ante eu ipsum vehicula, ut lobortis sapien tincidunt. Duis viverra, nibh quis consectetur aliquam, libero ex varius nunc, nec condimentum ipsum sem ac nisl. Vivamus blandit nisi viverra finibus tincidunt. Phasellus molestie scelerisque felis ut convallis. Praesent ut rutrum nisi. Quisque sed elementum nunc. Sed accumsan luctus tortor, sed volutpat neque pulvinar eu. Mauris ut finibus elit. Nullam lobortis, elit vitae ornare ultrices, nisi ipsum efficitur velit, vel bibendum ligula tellus nec massa. Nullam sit amet nunc tellus. Maecenas fringilla ligula eu commodo molestie. Nunc hendrerit, ipsum eu commodo vulputate, ligula justo tincidunt purus, sed vehicula enim enim at nisl. + +Curabitur venenatis ante vel luctus vestibulum. Ut sit amet nisi id tortor sollicitudin ultrices. Morbi sed est at nunc scelerisque accumsan volutpat volutpat mi. Etiam euismod sapien eu tempus laoreet. Curabitur consequat consectetur justo non porttitor. Ut convallis sagittis gravida. Nullam ornare luctus est, at viverra purus pretium sed. Aliquam vehicula risus nec auctor placerat. Ut libero sapien, viverra ac gravida eu, fermentum id nisl. Pellentesque ac ligula nec risus consectetur pretium. In eu magna quis augue imperdiet lacinia. + +Nunc dignissim mollis nibh ut malesuada. Fusce tincidunt euismod lacus non aliquet. Donec malesuada, nisl a volutpat pretium, purus turpis condimentum orci, eu blandit justo quam sit amet orci. Nullam blandit lobortis ligula tincidunt malesuada. Cras in pharetra justo. Nullam aliquet libero fermentum odio dignissim, a convallis sem vestibulum. Praesent hendrerit laoreet viverra. Vestibulum pulvinar odio eu imperdiet ultricies. Suspendisse a augue vehicula, maximus enim non, ultrices neque. Duis eu quam nulla. Nam condimentum enim at nisl commodo, vitae placerat eros condimentum. Nam molestie sem justo, nec lobortis lacus elementum ut. Nullam aliquam tortor sit amet odio commodo sodales. + +Ut nec magna a ex malesuada laoreet. Cras blandit dui ac sem fermentum blandit. Donec quis ultricies metus. Nam nunc odio, molestie nec arcu vitae, ultrices placerat felis. Proin tristique tortor sed lectus facilisis, in hendrerit massa dignissim. Suspendisse lacinia finibus lorem eu feugiat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean vehicula urna felis, sollicitudin varius leo vestibulum ut. Maecenas orci sapien, eleifend sed lacus nec, sollicitudin ultricies erat. Nunc non semper neque. Aenean sit amet efficitur eros. Vivamus eleifend, est vitae lacinia sollicitudin, orci enim tincidunt diam, vel feugiat arcu enim quis tellus. Mauris facilisis dui non tortor elementum tempus. Praesent commodo rhoncus felis, nec facilisis ex rhoncus nec. In mattis feugiat magna vitae imperdiet. Integer velit lectus, placerat sit amet convallis id, bibendum et justo. + +Pellentesque dictum semper nibh, ut egestas metus varius et. Sed tortor metus, consectetur non sollicitudin sit amet, pretium sodales libero. Fusce venenatis elit rutrum, rutrum tellus et, laoreet diam. Integer ac tristique tellus. Quisque varius elit magna, ac dapibus augue vestibulum vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur nec nisi laoreet, accumsan tellus in, auctor enim. Aliquam erat volutpat. Integer mollis lorem non scelerisque mattis. Vivamus non turpis massa. + +Aenean sed luctus felis. Aenean gravida velit posuere bibendum hendrerit. Donec non pulvinar erat, a placerat sem. Pellentesque in tristique dolor. Nulla non lacinia tortor. Morbi eu dictum mi, at suscipit nulla. Sed vitae risus viverra, viverra lectus id, lacinia eros. Donec in orci vel massa auctor iaculis id at orci. Vivamus nec libero at massa aliquet blandit. Curabitur accumsan ultricies augue, vel consectetur justo ullamcorper id. Aenean nec rutrum orci. + +Donec placerat nibh eros. Praesent faucibus bibendum libero, cursus vulputate dolor. Mauris rhoncus sed tortor eget rhoncus. Quisque ac est lacinia, eleifend odio in, tempus ipsum. Suspendisse tempor magna enim, maximus pharetra nulla pretium nec. Nullam euismod dictum justo sed porttitor. Ut et ligula ac ipsum consectetur viverra quis rutrum erat. Sed imperdiet non lectus eu pretium. Nullam blandit auctor rutrum. Morbi lacus neque, vehicula vitae sem sed, sodales placerat nulla. Integer cursus interdum vestibulum. Nunc ut ullamcorper ante. Aenean in cursus libero. + +Sed accumsan vel elit a porta. Fusce ante mi, egestas ut ex at, pellentesque pharetra enim. Aliquam non rhoncus mauris. Mauris iaculis magna porttitor sem eleifend, dignissim fermentum diam commodo. Quisque ultrices nisi sed felis tempor ornare. Ut sit amet hendrerit tellus, sed lacinia sem. Integer sit amet condimentum lectus, nec rutrum risus. Donec aliquet leo a sem varius, ut malesuada velit dictum. Mauris sit amet egestas tortor, et faucibus lorem. Donec ut ipsum et nisl pellentesque blandit ut ut lacus. Nam dolor mi, malesuada in posuere ac, dictum quis nunc. Quisque egestas tincidunt lacus. Suspendisse elementum tempor volutpat. + +Sed posuere tortor libero, sed gravida nulla efficitur ac. Aenean auctor arcu non diam fringilla accumsan. Suspendisse tincidunt massa quam, non pellentesque ex mattis sit amet. Mauris vel volutpat ligula, sit amet ornare nisi. Donec fermentum, diam sed blandit rutrum, nisi sapien ornare nisi, vel consectetur ex nibh sed mauris. Mauris varius posuere ligula quis consectetur. In nec sem vel enim consectetur vehicula quis sed erat. Donec vel ultrices mauris. Proin rutrum, risus a fermentum faucibus, nisi velit pellentesque est, eu ultricies ex sem rhoncus risus. Aliquam purus massa, dignissim vitae rhoncus sollicitudin, blandit laoreet lacus. Sed non elit hendrerit, posuere ex et, rhoncus nisl. Phasellus id viverra turpis. Nullam vel mauris non odio auctor auctor. Vestibulum id imperdiet dolor. + +Curabitur pretium luctus tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque risus justo, condimentum eu sollicitudin ut, lobortis quis libero. Aenean id dignissim odio. Nunc dictum vitae tortor nec pretium. Suspendisse vestibulum tellus a imperdiet rhoncus. Cras molestie est nunc, quis venenatis est convallis quis. Aenean mattis sapien et sapien tincidunt vulputate. + +Quisque sed enim nec libero fermentum faucibus. Donec blandit semper mi id sollicitudin. Praesent laoreet ante ut arcu aliquet, vitae mattis tortor condimentum. Sed fringilla ultrices dignissim. Mauris volutpat ipsum quis felis cursus, nec rhoncus massa egestas. Aliquam erat volutpat. Proin sem enim, gravida non risus ac, suscipit gravida tellus. Suspendisse mi turpis, mattis sed tellus vitae, finibus laoreet augue. Vivamus quis diam felis. Morbi cursus dui erat, eget blandit magna posuere ut. + +In odio neque, blandit id tincidunt et, facilisis vel eros. Donec ac mollis velit. Nunc a tortor viverra, malesuada neque non, posuere felis. Etiam eget sodales purus, vitae sagittis ex. Pellentesque eleifend risus sit amet porta rutrum. In eros lacus, condimentum nec purus at, porttitor porttitor turpis. Fusce sagittis hendrerit scelerisque. Praesent rutrum rhoncus mi eu facilisis. In maximus enim quis tempus volutpat. Maecenas pharetra erat non dui hendrerit, eu ultricies libero dapibus. Maecenas ornare molestie eros, quis ultricies orci. Nullam vestibulum sapien nec enim suscipit ultrices. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Duis tempus dui at leo auctor auctor. Phasellus et luctus felis. Duis finibus gravida tortor, sit amet suscipit augue vulputate a. + +Phasellus sit amet malesuada ante. Curabitur ultrices, magna quis efficitur pretium, libero lectus eleifend quam, ac egestas enim purus vitae nibh. Aenean ac eleifend libero, porta dictum erat. Quisque sit amet mi nibh. Nulla euismod, est ac tincidunt tristique, libero neque rutrum nisi, sit amet mollis augue tortor ultrices nisi. Nullam finibus orci lectus, eget scelerisque nisl condimentum at. Pellentesque porta, sem sed bibendum condimentum, risus quam ornare nibh, ut malesuada orci ligula sit amet augue. Ut mattis velit tempor feugiat suscipit. Phasellus mattis commodo cursus. Quisque sit amet urna risus. Donec bibendum sem turpis, vitae auctor magna aliquam vitae. Donec faucibus venenatis magna. + +Praesent nisi dolor, accumsan ut commodo ac, vestibulum in orci. Suspendisse a mauris eu enim lacinia elementum. In vitae gravida tellus. Nunc mi ligula, cursus nec viverra ac, gravida hendrerit lorem. Aliquam id purus consectetur enim vestibulum mollis. Vestibulum porta iaculis neque, non imperdiet erat consectetur a. Nullam tincidunt augue arcu, in consectetur nisi posuere at. Praesent accumsan pretium odio at interdum. Morbi pharetra efficitur purus a viverra. Proin a quam vel eros tincidunt venenatis non quis neque. Proin gravida purus non ante varius, at auctor quam venenatis. + +Sed et erat ut purus maximus ullamcorper. In sed sem sed mi aliquet scelerisque et in libero. Quisque consectetur, lacus et cursus dictum, velit metus consectetur dolor, id tempor orci nisi vel urna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Suspendisse faucibus, turpis eget tincidunt imperdiet, dui enim malesuada diam, id bibendum est quam et ante. Etiam finibus dolor eros, nec porttitor mi euismod vel. Proin pretium urna eget lectus congue, sit amet varius nunc tristique. Pellentesque tempor turpis et nibh laoreet pulvinar. + +Nulla congue ante in dolor pretium feugiat. Fusce vel eleifend leo, nec porttitor augue. Ut id leo ac metus vestibulum auctor nec et lectus. Morbi et tincidunt ex. Nulla feugiat dui eu elementum tristique. Mauris non metus augue. Aenean sodales eu nisl sed rhoncus. Vivamus vestibulum, massa nec semper varius, velit lorem accumsan ipsum, a porta sapien purus quis diam. Maecenas posuere finibus justo in sollicitudin. + +Duis augue sem, vulputate id elit a, cursus efficitur turpis. Aliquam consequat leo a dapibus euismod. Cras porta lacus ut rhoncus elementum. Aenean faucibus ut ipsum eu hendrerit. Nullam eleifend sagittis libero vitae sagittis. Nam varius, lacus nec vestibulum eleifend, sapien purus auctor ligula, non fermentum massa dolor at libero. Nunc eleifend turpis a orci maximus mattis. Nullam mattis turpis quis mi porta mollis. Maecenas commodo odio quis tellus placerat accumsan. Cras eleifend lacinia arcu in aliquet. + +Nullam mollis pretium varius. Morbi feugiat nunc nec felis finibus, eu tempor risus porttitor. Donec eleifend rutrum ex, in condimentum enim accumsan ut. Maecenas porta lectus lorem, eget consectetur risus vulputate eget. Vestibulum luctus turpis ultrices aliquet interdum. Aenean vulputate et nulla at porta. Sed vel ante turpis. Quisque ut mollis massa, ac tempus nisl. Quisque a vulputate leo. + +Quisque sodales molestie sollicitudin. Mauris quis felis id quam rhoncus cursus. Ut pharetra, ipsum sed malesuada pretium, nunc orci tincidunt lacus, id maximus ipsum quam at orci. Integer auctor lectus ac tempor mattis. Suspendisse nec vulputate neque. Morbi posuere velit vel faucibus ornare. Donec dignissim bibendum aliquam. Nam viverra eu erat in congue. + +Donec ut turpis varius, luctus quam eu, aliquet ipsum. Nam porta iaculis justo nec feugiat. Etiam vestibulum tristique neque id lobortis. Aliquam tincidunt enim ac arcu posuere, eget vulputate nunc commodo. Suspendisse finibus lectus vel ornare auctor. Integer felis dui, interdum eu lacus sed, placerat malesuada felis. Pellentesque ultricies volutpat nisi, at luctus augue faucibus a. Aliquam lobortis tempor nisi, sed fringilla orci accumsan nec. Cras interdum libero et eros varius tristique. Fusce consequat porttitor enim, quis ullamcorper magna tincidunt sed. Vestibulum tincidunt rhoncus purus nec mollis. Duis urna nunc, placerat in diam ut, semper posuere diam. Nulla bibendum tortor quis eros porttitor, nec pellentesque ante consectetur. + +Phasellus blandit laoreet suscipit. Sed gravida ut mi nec elementum. Morbi rhoncus eros non lectus vestibulum, quis lobortis augue molestie. Etiam posuere lectus mauris, vel lobortis arcu scelerisque et. Integer ligula diam, cursus eu velit in, vestibulum mollis libero. Ut nec elit vulputate, accumsan odio id, dignissim lacus. Donec tincidunt, velit eget facilisis molestie, magna sapien suscipit tellus, vel lobortis nibh velit vitae tortor. Quisque blandit malesuada consectetur. Integer sagittis consequat consequat. Sed tempus lobortis eleifend. Aliquam a augue id nisl porta malesuada. + +Nulla venenatis malesuada tortor non commodo. Nam non sollicitudin ex. Nam eleifend consequat metus, eget fringilla nisl facilisis in. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse accumsan accumsan mauris sit amet condimentum. Maecenas non neque convallis, porttitor ligula ac, consequat ante. Fusce vitae mauris vitae diam posuere semper vel at ante. Duis tempor ligula nec velit tempus, at commodo ex rutrum. Nullam ut ultrices ex, eu euismod sem. Donec in purus sed lacus aliquam dignissim. Ut gravida, leo id pellentesque ornare, purus diam tincidunt justo, eget vulputate libero justo semper felis. Donec lectus odio, aliquet nec lobortis et, facilisis vel turpis. Suspendisse egestas tortor sit amet lorem fermentum, in eleifend augue egestas. + +Suspendisse scelerisque risus sed risus tincidunt eleifend. Nullam dictum lacinia mauris, id fermentum purus maximus eget. Phasellus massa ante, tempor eu tempus tempus, pretium sit amet massa. Fusce in elit in lorem congue tempus. Pellentesque lorem massa, scelerisque non magna vel, pretium placerat sapien. Maecenas mattis nisl eu ante maximus varius. Mauris et feugiat nunc. Cras tincidunt metus mattis, fermentum felis vel, dignissim nisl. Mauris sodales turpis eget tellus malesuada ornare. Maecenas ut lorem eget nisi lobortis maximus. Nunc tempus blandit cursus. Vivamus mollis velit sapien, in scelerisque odio vestibulum non. Aliquam eget nulla bibendum lectus tincidunt vestibulum. Maecenas tincidunt dui in porta viverra. + +Vestibulum eu urna lectus. Sed felis metus, tincidunt ut vehicula sit amet, malesuada at dolor. Sed erat magna, convallis eget vehicula sed, feugiat nec lorem. Aliquam euismod dolor sem, sed gravida nisi commodo vitae. Suspendisse semper massa eu sapien iaculis, at fermentum lorem facilisis. Mauris dignissim lacinia suscipit. Etiam porttitor, felis non hendrerit aliquam, arcu arcu dictum diam, ut molestie orci massa ut nisl. In nec mollis neque. Nulla facilisi. Praesent lobortis fermentum enim non rhoncus. Nam malesuada quam mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Quisque sodales sapien in faucibus tristique. Duis at metus nibh. Integer varius lorem arcu, eget laoreet metus semper vel. + +Aliquam ullamcorper, lorem vitae fermentum tincidunt, neque sapien faucibus libero, sit amet blandit nunc elit eget nulla. Nam a nulla tortor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce ut tincidunt lacus. Curabitur tempor, tellus id ultrices vulputate, nibh elit aliquam odio, id pharetra justo nibh non ex. Donec tortor nisi, molestie non magna nec, malesuada laoreet ante. Nunc non ex vel sem dictum ornare sed id ipsum. Aliquam id purus dignissim, viverra lorem ac, congue leo. Nulla tempor tempus aliquet. Proin posuere, odio sagittis feugiat iaculis, nulla ligula tempor nisl, quis accumsan diam libero vel tellus. Etiam varius congue porta. Mauris consectetur erat non diam mollis, ut hendrerit ligula tempus. Ut cursus, risus ac cursus eleifend, massa eros interdum est, placerat luctus purus erat at magna. + +Maecenas pellentesque, augue ut vestibulum eleifend, nibh lacus dapibus mauris, in fermentum est risus fermentum orci. Sed interdum vitae eros at placerat. Duis at dapibus dui. Praesent malesuada dolor quam, vel vestibulum mauris pharetra vel. Duis nec fringilla magna, quis consequat dolor. Fusce lacinia justo et eros condimentum commodo. Nullam eu volutpat neque. Pellentesque tellus purus, feugiat non facilisis vel, ultricies a urna. Nulla pretium ac enim vel molestie. Vivamus vestibulum enim in interdum efficitur. Aliquam finibus nec turpis at eleifend. + +Integer vestibulum diam leo, nec aliquet odio sollicitudin quis. Duis ante enim, ultricies eu ultricies eu, tempus quis nunc. Fusce in orci at metus vestibulum porta venenatis eu ipsum. Cras ullamcorper ligula et ornare scelerisque. Donec dignissim orci et ex blandit, consectetur varius orci suscipit. In hendrerit lorem a venenatis suscipit. Cras sagittis fermentum consequat. Curabitur vitae quam fringilla, pulvinar libero non, dapibus nibh. Etiam velit diam, vehicula vel nulla id, tincidunt volutpat ante. + +Fusce sed tempor dui. Pellentesque sed nisi mattis nulla commodo lobortis. Integer at ligula quis eros hendrerit faucibus in eget libero. Praesent fringilla sodales leo, efficitur tempor purus venenatis in. Curabitur viverra placerat nisl non ullamcorper. Duis volutpat dui bibendum volutpat ullamcorper. Ut sodales erat tortor, eget sagittis lorem posuere non. Vivamus bibendum maximus est at luctus. + +Vivamus vitae mauris suscipit, rutrum risus ac, congue risus. Donec non nisl efficitur, feugiat diam a, blandit quam. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec sed pretium ipsum. Sed quis nibh ultricies ex scelerisque dictum. Fusce rhoncus luctus dictum. Aenean et fermentum ipsum. Vestibulum ipsum neque, viverra a orci in, aliquam pulvinar ante. Suspendisse convallis nisi eget arcu tincidunt hendrerit. Phasellus in elit at leo tristique pretium in eu orci. + +Vestibulum efficitur vehicula semper. Aenean ullamcorper condimentum nunc ac auctor. Vivamus tempor id risus sed vehicula. Suspendisse fringilla velit sit amet est interdum iaculis. Vestibulum ultrices interdum tempor. Cras eleifend congue efficitur. Nulla quam libero, rhoncus eu odio sed, commodo luctus tortor. Curabitur pulvinar ut justo ut tempus. Maecenas vitae ligula facilisis, ultricies felis ac, commodo diam. Maecenas scelerisque commodo risus, quis placerat lacus ultricies id. + +Sed elementum iaculis accumsan. Sed iaculis vel tellus ac commodo. Vestibulum magna massa, condimentum non mi non, egestas aliquet sapien. Suspendisse nisi nibh, consectetur a ipsum auctor, hendrerit pharetra elit. Suspendisse potenti. Nam mattis, mauris ullamcorper luctus pretium, felis ante sollicitudin massa, id dictum tortor sem ut ante. Cras sed neque ut libero condimentum laoreet. Donec accumsan ultrices velit sed bibendum. Proin nec velit vel mi fermentum tincidunt eget quis mauris. Quisque fermentum elit odio, sed imperdiet turpis tincidunt eu. Nunc in venenatis erat, vitae egestas dolor. + +Donec dictum fermentum orci, eu maximus velit interdum a. Sed molestie consequat ex a aliquam. Nullam quam nisl, iaculis quis justo ut, tincidunt lobortis nulla. Nullam eu dictum mauris. Maecenas fermentum nisi in urna pharetra, a placerat felis lacinia. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse eu consequat odio. Donec aliquam elit sit amet magna suscipit iaculis. Duis nec odio at augue varius venenatis non a mi. Proin suscipit, erat et pulvinar consectetur, leo ligula tempus turpis, blandit cursus libero massa non ligula. Nulla mollis aliquet ante, a imperdiet lorem maximus in. Nunc a diam sed ligula malesuada viverra ut non lectus. Praesent eget convallis nibh, ut volutpat nulla. + +Nulla viverra accumsan rhoncus. Vestibulum eleifend finibus aliquet. In lacus sem, venenatis et nibh vel, accumsan feugiat orci. Fusce eu odio efficitur, mollis urna at, pretium enim. Aenean rutrum elit non magna commodo, eu mattis massa mattis. Aenean porttitor hendrerit risus aliquam fringilla. Proin nisi magna, ornare et quam a, mattis tincidunt tortor. Vestibulum hendrerit convallis justo eget blandit. Nam porttitor eu felis non eleifend. + +Duis volutpat, magna vel venenatis vestibulum, nunc nunc fringilla tellus, a vestibulum lorem elit at nulla. Aliquam condimentum libero eu leo tincidunt ultricies. Etiam commodo, lectus nec cursus eleifend, leo nisl cursus dolor, sed feugiat felis massa quis lectus. Nulla imperdiet ligula sit amet justo congue, nec cursus lacus aliquet. Sed ante velit, laoreet pellentesque congue a, iaculis et lacus. Integer dolor dolor, accumsan vitae felis eu, tincidunt gravida lectus. Nullam vehicula nisi at hendrerit porta. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum placerat mollis justo sed tempus. Cras vehicula lacinia ligula, in rhoncus tortor. Morbi dignissim neque ut dui finibus pellentesque. In hac habitasse platea dictumst. Maecenas vehicula nec elit id viverra. Morbi vel nisl condimentum libero euismod pretium sit amet quis nibh. Morbi in blandit mi, vitae condimentum sem. + +Nam sagittis ut urna eget efficitur. Phasellus vel lacinia tortor. Suspendisse dignissim vestibulum commodo. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin efficitur sapien sed ipsum tempus, consequat consectetur felis tincidunt. Sed rutrum ex vel nibh efficitur, id fermentum leo sollicitudin. Nunc quis mauris nisi. Donec efficitur nunc vehicula eleifend ornare. Etiam nibh nulla, efficitur a tempus a, imperdiet ac risus. Curabitur in massa vel sem posuere pretium ac id erat. Integer volutpat ornare est at pharetra. + +Ut non purus id lorem suscipit congue id quis nunc. Aliquam id eros convallis, venenatis turpis ac, bibendum sapien. Sed fermentum lorem sed venenatis varius. Integer at massa ut ante lobortis porta vulputate quis ante. Curabitur vitae nulla sed augue ornare eleifend. Sed et lacus dolor. Suspendisse bibendum dolor et finibus efficitur. Etiam ut viverra arcu. Curabitur scelerisque, odio vel congue porttitor, nisl lectus viverra erat, lacinia vulputate leo est id mauris. In aliquet urna neque, eu aliquet odio tristique eu. + +Phasellus non tempor mi. Aliquam sed est interdum, auctor risus vitae, aliquet turpis. Sed tempus, velit non tincidunt auctor, libero odio lobortis purus, et efficitur magna ligula sit amet tellus. Maecenas hendrerit mauris vel nisl volutpat, vel fermentum nulla mattis. Praesent nec massa in justo cursus gravida. Fusce commodo velit vitae turpis facilisis condimentum. Phasellus ipsum nibh, congue eget venenatis non, lacinia sit amet nunc. Maecenas ornare nibh in mauris pellentesque lobortis. Quisque faucibus iaculis leo, non rutrum nunc vestibulum ac. Fusce a nisl laoreet, hendrerit tellus at, consectetur nibh. Fusce ac cursus elit, hendrerit placerat orci. Quisque maximus justo a arcu blandit tincidunt. Maecenas egestas dolor sagittis lectus dignissim consequat. Proin ut congue orci. Maecenas ut vestibulum dolor, ut commodo magna. + +Maecenas luctus libero ut dapibus ornare. Duis tincidunt, dolor sit amet placerat sodales, urna arcu elementum ipsum, a convallis lectus nunc nec eros. Sed porta porta efficitur. Etiam sagittis bibendum accumsan. Quisque dictum dui mauris, molestie cursus nibh fermentum nec. Aenean odio massa, mollis id pellentesque eget, finibus non nibh. In sagittis, turpis a ultricies feugiat, dolor tellus fermentum lacus, sit amet sodales orci velit ut dolor. Sed quis dolor id magna cursus hendrerit. Maecenas vehicula congue velit non blandit. Vestibulum in arcu vestibulum, sollicitudin mauris at, viverra ex. Nunc consectetur sagittis faucibus. + +Sed lectus libero, tincidunt a nisl ac, ornare mollis lorem. Nam id dolor id erat dictum sagittis. Vestibulum eget feugiat ipsum. Donec at nibh gravida, porttitor leo sit amet, posuere erat. Nulla facilisi. Nunc consequat, elit non accumsan egestas, ante velit convallis mauris, non mattis risus mauris in nibh. Phasellus et pellentesque erat, sit amet pretium orci. Ut porta felis sed dui consequat mattis. + +Mauris elit sem, mattis nec elit a, interdum pharetra augue. Fusce id tincidunt urna. Suspendisse a rhoncus orci, at ornare ex. In vulputate odio ac lacus interdum, vitae sagittis dolor blandit. Aliquam blandit ex ullamcorper, aliquet odio ut, sollicitudin risus. Nunc ac dui tempus, vestibulum justo scelerisque, vulputate arcu. Phasellus rutrum, magna eu blandit interdum, turpis ipsum ultrices nibh, non luctus leo augue eu risus. Curabitur ullamcorper, velit in mollis varius, massa orci tristique neque, vitae aliquet est mauris at purus. Proin quis viverra felis. Nullam quis tortor vel libero pretium viverra. Cras vitae suscipit ante, et egestas magna. Aenean sagittis, nulla ac sollicitudin sollicitudin, ipsum tortor laoreet nisi, eu accumsan tortor lorem non odio. Sed ut iaculis est, id efficitur odio. + +Ut aliquet, est vel pharetra consectetur, magna orci hendrerit felis, in tristique massa enim vel mauris. Quisque eu lorem egestas, porttitor magna eu, suscipit ligula. Aliquam erat volutpat. In massa mi, aliquam sed pretium vulputate, tempor vel velit. Pellentesque id ante turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In eget nulla mi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce a commodo felis. Suspendisse pellentesque neque odio, et aliquet metus sodales in. Donec euismod vel risus non efficitur. Phasellus ut nulla ac est consequat placerat et at arcu. Nulla facilisi. Pellentesque sit amet tellus cursus, gravida diam sed, egestas odio. Donec iaculis pellentesque ante quis tincidunt. + +Nullam condimentum est nec dui lacinia suscipit. Donec posuere bibendum egestas. Vivamus dignissim tincidunt massa non dignissim. Nam a ornare nibh, sit amet congue neque. Fusce tincidunt ligula in quam blandit dapibus. Duis eget ex bibendum, dictum ipsum quis, ullamcorper libero. Cras sit amet sapien hendrerit, dignissim mi et, iaculis nisi. Etiam ut dui sed lectus malesuada semper. Maecenas non tellus vulputate, aliquam justo vitae, laoreet velit. Pellentesque diam mauris, lacinia nec ex non, convallis efficitur elit. Nulla facilisi. Aenean porttitor efficitur varius. Duis vel metus vel diam sagittis suscipit. Cras id libero ac enim sollicitudin vehicula ac a augue. Pellentesque rutrum diam ut dapibus molestie. Donec malesuada iaculis cursus. + +Etiam commodo urna odio. Ut cursus ex libero, et pulvinar nisi placerat id. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec mollis vel purus lacinia laoreet. Quisque condimentum maximus urna vel scelerisque. Vivamus sagittis interdum faucibus. Integer eu eros volutpat, pharetra velit eget, ullamcorper augue. + +Sed mattis ultricies tortor, sit amet pretium arcu lacinia eu. Etiam sed porta est. Donec sit amet venenatis diam. Cras ut magna sed mi tempus feugiat. Maecenas nec metus lobortis, rutrum mauris rutrum, mollis nisi. Quisque scelerisque, risus vel lacinia aliquam, dui augue luctus orci, rhoncus sagittis urna metus eget elit. Mauris imperdiet augue sem, quis efficitur diam varius rhoncus. Suspendisse id rutrum lorem. Nullam porttitor consequat felis non feugiat. Sed dignissim egestas tempor. Vestibulum euismod laoreet dui vitae efficitur. + +Praesent arcu mauris, molestie sit amet porttitor ac, sodales id dui. Aliquam sed facilisis tortor, eget pulvinar purus. Proin malesuada at mauris ac volutpat. Proin cursus non quam id imperdiet. Morbi et dolor non leo finibus volutpat. Sed nec augue purus. Fusce eleifend mauris convallis nibh facilisis, sed pulvinar ante pellentesque. Sed nunc nisl, pulvinar at finibus at, gravida sed lorem. Cras sit amet accumsan enim. Vivamus est ex, gravida ac semper et, ultricies sit amet libero. Vestibulum quis vulputate velit. Cras convallis, erat vitae rutrum euismod, urna enim hendrerit mi, sed placerat metus erat eu sem. Ut id libero ipsum. Maecenas leo libero, aliquet malesuada mauris ac, facilisis aliquet magna. Donec vulputate lectus turpis, nec pharetra leo egestas at. Suspendisse rutrum risus vel orci lacinia, sed aliquam urna consequat. + +Curabitur mattis pretium turpis a pretium. Aenean consectetur, nibh id tincidunt mollis, ante purus finibus sapien, a lobortis nunc lacus id odio. Etiam cursus pharetra erat eget hendrerit. Sed aliquet, neque sed tempor tincidunt, tortor velit imperdiet ex, id gravida quam sapien in lacus. Proin eleifend consectetur lectus, quis dapibus ipsum varius vel. Integer sed volutpat leo, ut ullamcorper velit. Pellentesque elit lorem, scelerisque eu sapien quis, pulvinar faucibus diam. Sed placerat, urna a tempus eleifend, sem velit pulvinar nisl, in imperdiet erat purus eu purus. Quisque purus dolor, condimentum vel condimentum vitae, faucibus et enim. Vestibulum in magna quis mi blandit euismod sed ac tellus. Aenean sollicitudin eget sapien vitae tempor. Etiam maximus id mi at mollis. Sed auctor odio ac nunc varius efficitur. Suspendisse ante purus, luctus quis pretium a, scelerisque at tellus. Quisque ac ex a ante semper porta non sit amet nibh. Mauris lorem quam, consequat in aliquam at, tempor eu neque. + +Vestibulum pharetra dolor vel blandit mattis. Fusce ut aliquet mauris, eu fermentum tortor. Curabitur ornare tempus malesuada. Maecenas feugiat metus augue, in ullamcorper dui porta in. Cras erat eros, pharetra et nisi id, faucibus ullamcorper magna. Nam fringilla nulla ut neque placerat vulputate. Suspendisse vestibulum lacus ac orci aliquam ultrices. Maecenas porta rutrum arcu, nec fringilla leo scelerisque vel. Donec vitae accumsan justo, eu scelerisque elit. Nam non pretium justo. Proin in pellentesque metus, non dignissim sapien. Nullam maximus purus sed tincidunt venenatis. Phasellus tincidunt ligula a lectus semper, vitae laoreet lacus volutpat. + +Maecenas ut leo varius, fringilla felis at, faucibus sapien. Vestibulum at sapien rhoncus, efficitur lorem nec, interdum lectus. Fusce euismod ipsum libero, et aliquam urna venenatis sit amet. Mauris eget tortor sit amet lorem mattis condimentum quis ultrices odio. Nam id blandit magna. Nulla vestibulum luctus quam et hendrerit. Fusce nec purus pharetra, consequat risus quis, finibus tortor. Mauris ac dolor eu arcu sodales facilisis ut vel lectus. Ut auctor volutpat dictum. Etiam in faucibus metus. Donec mattis orci at gravida pellentesque. Aliquam tincidunt metus nisi, quis aliquet dolor commodo dapibus. Phasellus eget nunc sodales, gravida erat a, sollicitudin mi. Sed luctus condimentum justo ultricies ornare. Morbi quis felis fermentum, laoreet ipsum et, consequat ex. + +Aliquam erat volutpat. Nunc accumsan ex tortor, in ultricies tortor lobortis et. Phasellus convallis nunc sed arcu semper, ut consectetur lorem pellentesque. Nam vulputate maximus elit, quis auctor urna placerat at. Vivamus sit amet justo et nulla euismod aliquam vel ut quam. Proin blandit lacinia quam id tincidunt. Etiam ornare auctor sapien mollis faucibus. Maecenas commodo porttitor purus in mollis. Vestibulum sed nisi quam. Curabitur maximus ultrices lacus, sit amet sagittis leo faucibus eget. In eget justo semper, porta est lobortis, tincidunt ligula. Donec pharetra interdum elit, vitae vehicula libero viverra et. + +Praesent laoreet sit amet eros id tincidunt. Donec laoreet posuere nisi non mattis. Nunc iaculis imperdiet risus, sodales tristique ante vehicula eu. Vestibulum condimentum tempus hendrerit. Vestibulum eleifend eleifend felis, sed ultrices enim rutrum at. Praesent elementum justo id laoreet interdum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut sed interdum metus. Fusce sit amet luctus libero, ac efficitur nulla. Suspendisse volutpat est faucibus urna imperdiet dictum. Nunc sit amet euismod elit. Morbi sit amet rhoncus sem. Morbi tincidunt turpis at gravida tempus. + +Donec efficitur eget arcu ac tristique. Nullam bibendum libero consectetur purus dictum malesuada. Mauris a sapien urna. Integer dictum arcu a turpis consequat gravida. Fusce cursus lacus neque, ac efficitur erat feugiat at. Mauris eu arcu ut neque dignissim mattis a sed diam. Aliquam fermentum consectetur est eu vulputate. Vestibulum lobortis viverra diam vitae vehicula. Etiam non ligula nec felis tempus tincidunt. Praesent pulvinar tellus ac tortor imperdiet, at mollis nunc iaculis. Sed malesuada sapien non tortor convallis commodo sed at nibh. + +Sed a orci feugiat, dapibus sem id, condimentum tortor. Vestibulum commodo ut augue sit amet laoreet. Nam dignissim nec urna in vehicula. Pellentesque molestie lectus at rutrum luctus. Ut dapibus nec urna sit amet lacinia. Vestibulum ac arcu id diam fermentum iaculis. Cras suscipit erat sit amet mi congue volutpat. + +Donec non sapien sed elit luctus ullamcorper. Suspendisse varius sed leo et tempus. Duis convallis tempus elit, a efficitur ipsum ornare eleifend. Sed posuere felis at nisl dignissim congue. In volutpat tincidunt dignissim. Aenean ullamcorper ligula vitae lacus rhoncus, a ultricies nisl aliquet. Quisque ornare lectus nec erat aliquam efficitur. Nunc non diam placerat, dictum purus id, porta leo. + +Cras eget condimentum ex. Fusce et molestie diam. In euismod ullamcorper congue. Fusce pharetra sapien sit amet tortor egestas, vel luctus justo condimentum. Curabitur venenatis justo nec risus eleifend, id sodales felis commodo. Aliquam eros mi, tincidunt non tincidunt sit amet, sodales eget sapien. Mauris ac diam ac dolor fermentum iaculis sed sed velit. Phasellus libero augue, tempor non turpis in, dapibus ultrices lacus. Donec at ligula enim. Sed quis dolor augue. Nullam scelerisque elit lacus, eget viverra ante tempus at. Duis eget felis arcu. + +Nam euismod metus sapien. Fusce vel urna vulputate, laoreet risus non, ultrices nisi. Sed finibus nisl convallis tellus fringilla molestie. Pellentesque luctus blandit condimentum. Mauris tincidunt viverra nisl nec malesuada. Phasellus suscipit eros vitae arcu laoreet ornare. Nullam vitae orci vitae mauris auctor fermentum. Nulla in elit ac risus interdum dictum sit amet sit amet lectus. Pellentesque fringilla blandit ligula nec pretium. Aliquam gravida, quam quis tempor convallis, ligula metus elementum ex, eu commodo lacus nisi ac nisl. Cras quis odio erat. Nulla tincidunt nulla urna, sed commodo nibh malesuada id. Donec accumsan ultricies est nec vulputate. + +Phasellus ornare mauris purus, a hendrerit est vehicula eu. Cras ut interdum elit, non molestie nibh. Donec consequat ante et dignissim malesuada. In aliquet ante eget dui venenatis luctus. Morbi scelerisque ornare nibh, id mollis odio. Aliquam vitae fermentum felis. Praesent et viverra nisi. Fusce vulputate urna sit amet blandit rhoncus. Nunc vitae lacus orci. + +Phasellus ac viverra mauris, in viverra arcu. Fusce iaculis felis ut libero placerat, non dapibus nisi aliquam. Sed lacinia lectus in lorem congue, sed finibus tortor fermentum. Nam sit amet augue sit amet urna sagittis pulvinar in pretium neque. Vivamus convallis pretium mauris, non dictum justo tincidunt in. Suspendisse ac tellus lacinia, porta augue at, tempor augue. Sed lorem ligula, euismod sed massa sit amet, dapibus fringilla velit. Proin tellus dolor, convallis ut felis quis, luctus placerat diam. Donec tincidunt viverra sapien ut faucibus. + +Fusce ut sodales ante. Sed pretium laoreet ante a imperdiet. Morbi quis tincidunt turpis. Nam eleifend non turpis ornare porta. Vestibulum gravida quam lacinia leo bibendum fringilla. Donec justo augue, molestie a pulvinar eu, iaculis at orci. Mauris non tempus lorem, ac iaculis dolor. Nullam pretium, sapien a porta egestas, nulla arcu mattis nisi, nec hendrerit sem lorem in libero. Mauris congue ipsum orci, eu maximus mauris vulputate ac. Cras ex odio, porttitor id aliquet non, egestas vitae magna. Morbi egestas rutrum odio sed dignissim. Proin sit amet auctor enim. + +Suspendisse luctus est at nulla sagittis, id tincidunt sapien gravida. Cras ac eros nisl. Cras facilisis turpis et leo bibendum varius. Mauris laoreet urna in aliquam maximus. Pellentesque varius tortor eget pretium placerat. Proin aliquet dui ac ipsum mollis mattis. Vestibulum rutrum venenatis velit ut ornare. Pellentesque tempor mattis turpis, dignissim mollis arcu auctor eget. Donec eu pharetra lectus. Donec a tortor ut tortor eleifend convallis eu ut augue. Nullam nec odio tincidunt, ornare est eget, vehicula diam. Nulla facilisi. Nullam vel elementum velit. Nulla in massa eget dolor feugiat imperdiet nec ut mauris. + +Nullam ac efficitur eros, at faucibus enim. Praesent ultricies enim sodales venenatis blandit. Integer in sollicitudin metus. Aliquam erat volutpat. Nulla convallis lectus vel leo sollicitudin, sit amet mollis mi euismod. Mauris varius varius risus, aliquet dictum sapien ullamcorper non. Aliquam arcu leo, aliquet at commodo in, hendrerit eget diam. Donec mattis dapibus aliquam. In vel tempor felis. Mauris ac pretium velit, eget semper ligula. Nunc iaculis dapibus ipsum, at accumsan nisi dignissim eu. Ut vel elit dolor. Nunc sit amet condimentum nisi. Nulla in nulla eget dolor mollis euismod in a metus. Mauris id pretium lacus. + +Ut a nunc id velit ornare malesuada ut vel nulla. Maecenas vitae leo in justo ultricies bibendum. Ut est magna, consectetur eget nibh vitae, egestas eleifend arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam at posuere lectus, non lacinia lorem. Sed interdum justo non nunc malesuada, quis feugiat augue pellentesque. Ut gravida pulvinar neque at sodales. Ut et porttitor lacus, at condimentum nulla. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean fermentum imperdiet ante eu vestibulum. Vestibulum ligula nulla, tincidunt malesuada dignissim non, semper id erat. Nunc elit enim, faucibus id hendrerit ut, aliquet at tellus. Donec nec consectetur nulla. + +Sed ultricies molestie dictum. Etiam malesuada purus eros, id elementum arcu ullamcorper dapibus. Integer consectetur tortor augue, ac finibus ligula ultrices at. Aliquam vel euismod ex. Suspendisse bibendum id ipsum a venenatis. Etiam efficitur, risus at finibus blandit, lorem lorem ullamcorper risus, nec condimentum dui felis at eros. Morbi vel neque ac dolor fringilla eleifend. Proin varius lectus luctus ante tristique, ut blandit metus faucibus. Aliquam eu est gravida, tempor tortor a, maximus quam. + +Donec eget mollis ipsum. Aliquam odio mi, dictum a lacinia dignissim, hendrerit a ipsum. Sed ut augue vitae enim vulputate ultricies a nec dolor. Pellentesque finibus ante sed libero eleifend congue. Etiam sit amet metus at turpis euismod placerat. Morbi sit amet tempus libero. In eros quam, pretium a hendrerit sed, volutpat rutrum quam. Nulla egestas justo in orci euismod egestas. Morbi in consectetur risus. Sed porta ligula eu libero ultricies, sed hendrerit tortor sollicitudin. Morbi at diam fermentum quam fermentum porttitor. Sed placerat, ante id malesuada rhoncus, tellus lorem rhoncus tellus, a aliquam diam massa ut felis. Aenean sagittis metus ut placerat iaculis. Maecenas tempor venenatis molestie. + +Ut ligula odio, efficitur eu ante in, maximus aliquam purus. Aenean cursus, nibh vitae interdum tempus, ipsum lacus pretium felis, non finibus arcu nisi sit amet ex. Fusce in ex urna. Duis ut lobortis neque. Suspendisse elit purus, rutrum quis tellus id, porta euismod nisl. Maecenas vestibulum augue in tortor ullamcorper lobortis. Morbi non tellus finibus, gravida felis quis, feugiat ante. In quam felis, ultrices ac dictum malesuada, imperdiet eget nulla. Fusce commodo a mi et sagittis. Integer venenatis condimentum massa in consectetur. Duis non ornare est. Morbi ultricies congue odio, quis scelerisque enim eleifend at. + +Sed rhoncus mollis ultrices. Duis vel justo in leo tincidunt rutrum et ac sem. Nulla facilisi. Donec viverra enim ut lorem eleifend vehicula. Vestibulum pharetra tempor magna sed rhoncus. Proin tempor augue in posuere congue. In hac habitasse platea dictumst. Fusce elementum lectus purus, in aliquam lacus egestas ac. Nunc accumsan urna nec nisi posuere aliquam. Morbi metus dolor, lacinia sit amet lectus vitae, egestas pellentesque enim. Nullam imperdiet blandit ipsum eu pellentesque. Aenean in rhoncus velit. Donec mattis urna et blandit consequat. Nulla sit amet mi ut risus rhoncus viverra. Fusce tempor eget eros vitae volutpat. + +Mauris nec vulputate massa. Integer faucibus consectetur pellentesque. Etiam sagittis augue a ultrices elementum. Aenean at tincidunt nisl. Donec sed mi id neque pharetra auctor. Etiam malesuada, erat sed euismod fermentum, sem leo blandit massa, sed maximus augue risus sed sem. Aliquam scelerisque interdum lacus, quis congue risus efficitur et. Vivamus quis mollis massa. Curabitur at massa nec ligula efficitur sagittis nec in risus. Vivamus at sollicitudin odio. Proin eget orci feugiat, laoreet turpis a, maximus leo. Duis sed nunc dictum, posuere erat in, vestibulum lacus. + +Vivamus ut dignissim ex, vitae finibus erat. Pellentesque suscipit velit in sapien gravida varius. Ut non iaculis ligula, ac feugiat elit. Ut purus ligula, porttitor ac dapibus et, rhoncus vitae enim. Nam id commodo lorem, egestas convallis lorem. Mauris iaculis purus quis placerat vestibulum. Aenean ullamcorper varius placerat. Aenean odio quam, maximus ut posuere quis, consectetur ac tellus. Curabitur eleifend dictum urna vitae efficitur. Etiam vehicula, lectus a tempor sagittis, sapien nisl fringilla nulla, a venenatis risus nisi ullamcorper lorem. Maecenas eget quam sit amet orci tempor euismod. + +Integer vehicula nisl lectus, id mollis quam dapibus id. Vestibulum nec lobortis nisl, vitae tempor turpis. Etiam a vulputate neque, quis elementum tortor. Aenean nec placerat justo. Aenean sollicitudin porta laoreet. Vestibulum ut auctor ante. Pellentesque non eros sem. Pellentesque sagittis ac neque sit amet ullamcorper. Sed ac consequat tellus. Nunc sodales pellentesque nibh, eu maximus neque lobortis in. Ut luctus non nunc ut fermentum. + +Maecenas sed dapibus eros. Curabitur et arcu non nunc efficitur rutrum. Morbi egestas ornare ligula quis commodo. Vestibulum ac nisl id lacus commodo porttitor id tincidunt ipsum. Fusce a massa tortor. Nullam mauris erat, sagittis sed ex vitae, sagittis tempus arcu. Nam iaculis eget dui vitae ornare. Maecenas a urna lectus. Donec posuere velit id lectus tincidunt consectetur. Ut vehicula arcu mi. + +Sed eget nisi feugiat, maximus diam sit amet, lobortis velit. Praesent sed tortor quis turpis aliquam posuere. Proin condimentum augue in sem tincidunt faucibus eget at dui. Etiam in finibus sapien. Suspendisse enim nunc, tincidunt at tortor nec, sollicitudin tincidunt ante. Sed dapibus erat nisi, ut rutrum est suscipit nec. Donec finibus non diam quis sollicitudin. Vivamus ac magna aliquet, accumsan urna eu, tincidunt turpis. Vestibulum lacinia dignissim tortor. Sed dictum mattis ex vitae rutrum. Suspendisse tristique eleifend quam ac luctus. Aliquam erat volutpat. Sed ante sem, lacinia vel quam vel, dictum tempor orci. Etiam ac fringilla libero. + +Phasellus nunc metus, maximus sit amet tristique quis, dictum vitae neque. Cras convallis sem lacus, a malesuada ex vehicula vel. Phasellus ac pellentesque velit. Maecenas faucibus elit quis sapien venenatis, sit amet pharetra nulla venenatis. Donec volutpat feugiat urna, nec maximus lectus convallis ac. Nam ut consectetur ligula. Nam auctor erat ligula. Nunc posuere blandit felis, vel aliquam lectus. Pellentesque eget venenatis velit. Donec aliquet ipsum non odio dictum, cursus cursus dui bibendum. + +Nunc mollis, orci eget sollicitudin faucibus, nibh est tincidunt ex, et placerat magna justo laoreet arcu. Donec vel tempor enim. Donec sit amet velit ac neque sagittis gravida. Proin maximus, orci nec consectetur aliquet, elit erat rhoncus nisi, eu sodales ligula augue sit amet lectus. Proin ornare nisl a nisl ultricies, ut rhoncus diam rhoncus. Mauris aliquet volutpat ipsum in pharetra. Nullam in sagittis augue. Nunc blandit pharetra mi ac molestie. Fusce lobortis eu tortor non vestibulum. Donec felis augue, dictum id nisl eu, condimentum ornare est. Praesent ut nunc rhoncus, pulvinar ante molestie, consequat enim. Fusce viverra tristique massa ut dignissim. + +Nam eu justo ut tellus imperdiet tempor et id risus. Cras sed arcu rhoncus, euismod leo vel, sollicitudin libero. Cras lobortis ac nulla at semper. Vivamus nec risus consectetur, vestibulum erat id, bibendum augue. Suspendisse et leo non mi consequat aliquam feugiat eget lectus. Morbi pharetra augue nisl, eget tincidunt metus convallis vitae. Etiam congue ultricies lacus. Vivamus rhoncus aliquam aliquam. Nulla sit amet ante libero. Mauris sed condimentum augue. Aenean ut dui sit amet elit imperdiet tempor. Quisque finibus leo eget quam fringilla ultrices. Proin ullamcorper sollicitudin ante a pellentesque. Morbi a dictum ligula, et finibus magna. + +Curabitur semper dui eu diam viverra, et sollicitudin nisi posuere. Phasellus ultrices erat est, non eleifend mauris semper viverra. Proin lobortis massa erat, at consectetur neque mattis a. Nulla condimentum mauris in rhoncus ullamcorper. Pellentesque vitae lectus in velit tincidunt ornare vitae eget augue. Mauris elementum egestas lorem, eget bibendum neque finibus vitae. Fusce eget risus urna. Sed varius, libero id convallis ultrices, ligula mi fringilla sapien, vel vehicula metus enim eu ante. Nam dictum, est nec iaculis auctor, nunc ante mattis lectus, malesuada rutrum nisl lectus et orci. Cras sollicitudin lacus a sem ultricies consequat. Suspendisse potenti. Suspendisse feugiat, elit sed tincidunt molestie, lectus urna vulputate quam, sit amet eleifend nulla nisi quis nunc. Nam in magna in enim mattis condimentum. + +Donec vitae neque lorem. Quisque eget consequat leo, quis luctus risus. Vivamus suscipit dapibus placerat. Curabitur vitae mauris auctor elit tempor ultricies ac ac ligula. Sed sodales leo efficitur metus lobortis consequat rhoncus nec est. Aenean faucibus in ex at facilisis. Nulla sit amet dolor quis tortor vehicula bibendum. Nam eleifend, nibh et vulputate maximus, lectus velit rhoncus lorem, sit amet ullamcorper odio mauris non libero. Phasellus tincidunt enim a euismod convallis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras mollis placerat sem, varius vulputate urna viverra et. Pellentesque porttitor ex purus, ut laoreet est gravida vel. Donec tristique nibh non lectus dapibus, ut congue nibh molestie. + +Ut ullamcorper, est nec vehicula imperdiet, est sem posuere velit, id dignissim tortor dui sed lacus. Mauris quis dui at ligula tempor bibendum in sed felis. Nunc convallis leo eget arcu laoreet, sit amet tempor nunc egestas. Donec vel nisi vulputate, dapibus tortor dictum, semper velit. Suspendisse rhoncus ullamcorper erat, pharetra semper libero lacinia et. Nam quis eros ullamcorper, faucibus lacus id, laoreet odio. Nunc justo ex, tempor sed commodo ut, lobortis vitae ex. Cras ut felis at nunc ultrices tincidunt ut in diam. Duis vehicula orci et urna ullamcorper fringilla. Donec at quam fermentum, eleifend arcu id, aliquet enim. Praesent condimentum augue at neque varius, sed feugiat neque ultrices. Mauris non risus sit amet nisi facilisis suscipit. Sed sed elementum dolor, nec porta velit. Aenean at dui mauris. + +Proin cursus sapien eget justo tempor, sed maximus ligula sodales. In et viverra turpis, et euismod felis. Aliquam erat volutpat. Nunc congue laoreet tellus a congue. Nam lectus enim, malesuada sed tincidunt at, porta vitae purus. Curabitur quis ipsum faucibus augue suscipit euismod. Curabitur cursus porttitor mattis. Pellentesque eget efficitur libero. Integer in sodales diam, in suscipit enim. Donec egestas massa non sagittis dignissim. Aenean eleifend viverra neque quis faucibus. Praesent sed libero in diam mollis sodales. Etiam vel ultricies turpis, eget varius sapien. Quisque eu ligula ante. Phasellus mattis feugiat neque sit amet mollis. + +Proin non lectus ut tortor dictum euismod ut vel odio. Etiam vel velit magna. Curabitur eu orci vel tellus condimentum congue. Mauris porttitor diam lacus, ac fermentum nisl sagittis id. Praesent finibus massa diam, eget porttitor diam pellentesque in. Suspendisse in dictum ex. In aliquam maximus facilisis. Maecenas tellus enim, imperdiet id risus nec, eleifend molestie felis. Mauris vel magna quis tortor malesuada viverra. + +Morbi aliquet tortor at mattis semper. Vivamus auctor sagittis est, eget eleifend nisl condimentum id. Pellentesque mi eros, bibendum a congue sit amet, rutrum nec ipsum. Praesent gravida vitae lacus id faucibus. Donec condimentum ipsum quis semper vehicula. Etiam bibendum nibh quis libero finibus tincidunt. Donec scelerisque dapibus sem, eu tempus lectus finibus in. Donec a aliquet enim. Aenean dapibus finibus ipsum, id ultricies nunc porta mollis. Fusce viverra massa sit amet justo lobortis feugiat. Suspendisse fringilla dui eget augue mollis, vitae faucibus urna ultrices. Sed commodo risus vel nisi gravida suscipit. + +Nulla id scelerisque mauris, ac gravida libero. Curabitur non ultricies metus. Curabitur sed quam tortor. Integer feugiat blandit eros eu rutrum. Curabitur vestibulum sem id lectus iaculis cursus. Curabitur ullamcorper in risus eget blandit. Nunc id elementum justo. Etiam ac augue suscipit, bibendum mauris a, tincidunt libero. Sed pharetra ligula pulvinar accumsan bibendum. + +Duis pharetra imperdiet mattis. Curabitur nec posuere leo. Maecenas metus elit, consectetur volutpat lobortis sed, laoreet vitae odio. Duis congue sem ac porttitor dictum. Duis varius mattis ligula, sagittis pulvinar augue vehicula a. Donec vel commodo arcu. Vestibulum ultrices ligula enim, non viverra ex laoreet vitae. Mauris venenatis feugiat elit non aliquet. Vestibulum pellentesque metus at nulla lacinia, vel viverra felis auctor. + +Morbi lobortis, lacus quis consectetur porttitor, ligula elit fermentum mi, in ultrices elit justo a augue. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus dignissim, sapien ut convallis dignissim, risus augue tempor nunc, sit amet aliquam sem ante nec erat. Cras sit amet elit pulvinar, faucibus orci sed, dignissim odio. Aenean ultricies erat sit amet elit tincidunt, sed congue dolor fermentum. Ut ligula risus, fermentum quis purus quis, euismod scelerisque est. Integer vestibulum at mi vitae lobortis. Nullam urna quam, lobortis et dui quis, lobortis consectetur sem. Praesent ornare tellus vel leo porttitor, in finibus metus sodales. Donec pharetra, velit sit amet condimentum vulputate, dui quam hendrerit urna, nec viverra urna lacus ac ligula. Aliquam erat volutpat. + +Fusce pulvinar mi luctus eros semper, bibendum pharetra tortor ultricies. Curabitur at nisl vitae quam ultricies congue quis quis nibh. Curabitur in arcu ante. Donec blandit eget sapien at rhoncus. Maecenas eget justo nulla. Aenean auctor leo tortor, eu condimentum metus dignissim sed. Sed sit amet luctus urna. Aenean efficitur, quam et euismod rutrum, odio dolor mattis est, quis ornare risus libero interdum diam. Sed consectetur vestibulum dolor, consequat fringilla mi suscipit ac. Praesent euismod tincidunt lorem. Fusce a suscipit sapien. Suspendisse non placerat ante. Sed ut eros eget libero mattis tincidunt sed nec nisl. Ut a iaculis dui, quis maximus tortor. + +Quisque tristique arcu neque, ac laoreet orci feugiat sed. Nullam et est posuere massa scelerisque facilisis quis id eros. Pellentesque sit amet tellus est. Integer volutpat magna nec leo vulputate aliquam. Curabitur at odio sit amet nibh condimentum lobortis. Ut mollis mauris et risus laoreet, eget consequat urna blandit. Nam eu tempor dolor, et mollis elit. Aenean accumsan nunc at magna elementum dictum. Pellentesque urna justo, aliquet nec convallis sit amet, venenatis ac ante. Vestibulum ex tortor, feugiat sit amet lectus vitae, ultricies vulputate est. Duis eu suscipit nibh. Etiam porta lectus sed diam laoreet consequat. Quisque nec nibh justo. Pellentesque sed mauris orci. Praesent gravida tortor vitae eros vehicula, quis cursus diam viverra. + +Aenean mollis vitae ex eu commodo. Nullam in metus egestas, placerat arcu sed, finibus velit. Duis mollis dolor ac leo dapibus, et gravida elit viverra. Praesent faucibus blandit scelerisque. Etiam nisl odio, rhoncus id sapien id, consequat rhoncus nibh. Nam interdum turpis ipsum, at fringilla arcu maximus vitae. Proin viverra id turpis sit amet venenatis. Ut ullamcorper velit vitae justo imperdiet fermentum. Pellentesque ultrices pellentesque nibh ut rutrum. + +Aliquam vel venenatis lorem, sit amet pellentesque turpis. Vestibulum varius vestibulum purus, nec ullamcorper quam eleifend vel. Nulla lobortis varius nisl et dignissim. In id nisl vulputate, tincidunt augue et, porttitor risus. Suspendisse interdum velit sed tortor porta rutrum. Nullam tortor dolor, accumsan sit amet dui in, sagittis facilisis tellus. Fusce faucibus porttitor dui non rhoncus. Nulla ligula justo, interdum ac finibus sed, blandit a ipsum. Donec tincidunt efficitur ipsum, a luctus dui auctor eu. Sed efficitur hendrerit quam, ac faucibus urna egestas eget. Praesent enim lorem, auctor placerat dapibus eget, finibus eget orci. Praesent lectus ex, congue nec magna ac, ultrices scelerisque felis. Vivamus cursus mauris at ante venenatis vestibulum. Nunc vestibulum molestie venenatis. Sed a euismod leo, nec tincidunt nisi. + +Aliquam malesuada erat ac erat egestas facilisis. Aenean pulvinar vitae magna non mollis. Suspendisse aliquet ex nibh, eu maximus ante malesuada ac. Donec vel ultrices metus. Maecenas egestas arcu ligula, ac blandit tortor tincidunt aliquet. Donec rutrum, lacus eget interdum ultricies, ante leo rutrum risus, at semper lectus quam eu ante. Vivamus at eros ipsum. Donec et egestas ante. Donec mollis purus semper velit laoreet, a blandit mauris lacinia. Aliquam erat volutpat. Aliquam imperdiet tortor orci, nec sagittis mi viverra a. Nam sit amet mollis libero, in finibus nisl. + +Morbi elementum non nisi id fermentum. Sed dolor sem, rhoncus ut nisi vitae, gravida imperdiet felis. Maecenas a nulla rutrum, egestas metus non, auctor leo. Cras facilisis pellentesque nisi, in hendrerit elit mollis eu. Aenean sit amet lacus non tortor lacinia feugiat. Pellentesque dapibus sit amet purus at tristique. Sed pulvinar dignissim magna egestas interdum. Mauris feugiat est tincidunt massa cursus tincidunt. Maecenas dolor lorem, convallis id semper vel, dignissim eu urna. Nulla hendrerit velit dui. Donec sodales sed eros vel suscipit. Nullam ligula turpis, interdum nec ultricies quis, blandit non dui. Sed elit tellus, egestas vitae tempus vitae, ultrices eget nisl. Cras porta, neque vitae consequat pellentesque, eros quam gravida eros, a molestie lorem mauris sit amet velit. Morbi malesuada risus est, ut finibus justo maximus ac. + +Integer sagittis nunc sapien, id bibendum sapien mollis ac. Quisque elit quam, semper quis nunc at, porta fringilla libero. Donec non mattis quam. Etiam vel felis at turpis suscipit tempor. Sed velit sapien, ultrices eget orci quis, fermentum ullamcorper erat. Suspendisse eu lacus a nisi condimentum viverra varius vel turpis. Nam finibus ante mattis purus aliquet sodales id at nibh. Ut porta orci quis felis fringilla, eu elementum quam semper. Pellentesque ultrices volutpat nisl, vel varius dui pretium at. Pellentesque commodo orci ut urna condimentum, et elementum mauris posuere. Proin eget neque lectus. Mauris sollicitudin libero eu elit rhoncus, id fermentum arcu ultricies. Mauris elementum nisi a orci tempus, eu cursus eros cursus. Quisque blandit pretium erat, et viverra eros accumsan a. + +Donec porttitor ultrices velit, faucibus cursus diam aliquam nec. Vestibulum feugiat, libero quis ultrices luctus, ante enim euismod lectus, ut dictum felis lorem in ipsum. Phasellus magna lorem, pharetra sit amet lectus at, molestie eleifend lectus. Praesent volutpat ullamcorper sapien quis placerat. Proin a tellus eget nisl ornare luctus et non justo. Integer rhoncus, purus nec ultricies viverra, lorem libero vestibulum quam, vel euismod lectus nunc quis felis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean molestie dui a purus ultrices, eu condimentum odio ultricies. Integer maximus facilisis ultrices. Pellentesque est nisl, posuere a hendrerit vel, maximus ac justo. Nam eu sem suscipit, fringilla urna sit amet, sodales odio. Nullam feugiat porttitor convallis. Donec mollis fermentum tellus, vitae pretium felis vestibulum ac. Proin sodales ac nunc non congue. + +Nulla id mauris risus. Phasellus laoreet tortor at elit iaculis ornare. Sed elementum arcu purus, sit amet dapibus nisi mattis tempus. Praesent accumsan risus eu purus tempus, et semper nisl tincidunt. Phasellus sit amet urna ac est tristique vehicula vitae ac sem. Nullam fermentum aliquet nulla, ut maximus sapien aliquet lobortis. In eget mauris pharetra, imperdiet mi sit amet, aliquet eros. Vivamus et molestie magna. Cras tempus semper erat sit amet sodales. Aenean eu eros non tortor accumsan ultrices a nec nisl. Cras ac finibus purus, quis volutpat lectus. Nullam nisi metus, scelerisque a tincidunt sed, volutpat a lacus. Nam est ligula, porttitor a neque et, accumsan volutpat sapien. Curabitur placerat turpis eu mauris tincidunt posuere. Vivamus semper nibh velit, sit amet tincidunt sem blandit nec. + +Phasellus euismod suscipit mauris, in aliquam eros tincidunt vel. Nulla leo nisl, fringilla eget risus et, sagittis egestas dui. Etiam vel est vel erat dignissim maximus eu et nulla. Nunc ullamcorper blandit tellus sed condimentum. Nullam id bibendum sapien. Sed eget imperdiet eros. Sed non sapien sagittis, elementum metus at, egestas justo. In suscipit libero arcu. Mauris vestibulum diam lorem, eget malesuada velit fermentum ac. Aenean eu tellus massa. Proin eu semper massa. Ut in sem ac mauris varius fringilla at sed elit. + +Phasellus urna sapien, convallis id porta nec, tempus eu leo. Nunc et tincidunt purus. Integer at condimentum nunc, non pharetra justo. Donec vitae leo pharetra felis porta iaculis. Quisque sit amet mattis magna. Maecenas et malesuada lectus, eget hendrerit libero. Quisque eu congue urna, sit amet varius sem. Proin faucibus luctus viverra fusce. diff --git a/internal/test/gen/testv1/test.gw.client.go b/internal/test/gen/testv1/test.gw.client.go index c5fe93d..52efb4d 100644 --- a/internal/test/gen/testv1/test.gw.client.go +++ b/internal/test/gen/testv1/test.gw.client.go @@ -17,6 +17,7 @@ type TestServiceGatewayClient interface { SendInvitation(context.Context, *SendInvitationRequest) (*SendInvitationResponse, error) TrackInvitation(context.Context, *TrackInvitationRequest) (<-chan *TrackInvitationResponse, <-chan error, error) DownloadInvitations(context.Context, *DownloadInvitationsRequest) (<-chan *httpbody.HttpBody, <-chan error, error) + DownloadLargeFile(context.Context, *DownloadLargeFileRequest) (<-chan *httpbody.HttpBody, <-chan error, error) } func NewTestServiceGatewayClient(c gateway.Client) TestServiceGatewayClient { @@ -66,3 +67,8 @@ func (c *testServiceGatewayClient) DownloadInvitations(ctx context.Context, req gwReq.SetQueryParamsFromValues(q) return gateway.DoStreamingRequest[httpbody.HttpBody](ctx, c.gwc, gwReq) } + +func (c *testServiceGatewayClient) DownloadLargeFile(ctx context.Context, req *DownloadLargeFileRequest) (<-chan *httpbody.HttpBody, <-chan error, error) { + gwReq := c.gwc.NewRequest("GET", "/download-large-file") + return gateway.DoStreamingRequest[httpbody.HttpBody](ctx, c.gwc, gwReq) +} diff --git a/internal/test/gen/testv1/test.pb.go b/internal/test/gen/testv1/test.pb.go index 690c040..404ffea 100644 --- a/internal/test/gen/testv1/test.pb.go +++ b/internal/test/gen/testv1/test.pb.go @@ -568,6 +568,44 @@ func (x *DownloadInvitationsRequest) GetType() EventType { return EventType_EVENT_TYPE_UNDEFINED } +type DownloadLargeFileRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DownloadLargeFileRequest) Reset() { + *x = DownloadLargeFileRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_testv1_test_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DownloadLargeFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DownloadLargeFileRequest) ProtoMessage() {} + +func (x *DownloadLargeFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_testv1_test_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DownloadLargeFileRequest.ProtoReflect.Descriptor instead. +func (*DownloadLargeFileRequest) Descriptor() ([]byte, []int) { + return file_testv1_test_proto_rawDescGZIP(), []int{10} +} + var File_testv1_test_proto protoreflect.FileDescriptor var file_testv1_test_proto_rawDesc = []byte{ @@ -641,61 +679,70 @@ var file_testv1_test_proto_rawDesc = []byte{ 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x88, - 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x6c, 0x0a, 0x09, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x53, 0x45, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x56, 0x45, 0x4e, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x17, 0x0a, 0x13, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, - 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x32, 0x90, 0x04, 0x0a, 0x0b, 0x54, 0x65, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x4c, 0x69, 0x73, - 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x69, - 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, - 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x7d, 0x0a, 0x0e, 0x53, 0x65, 0x6e, - 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x69, 0x6f, - 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, - 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x84, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x61, - 0x63, 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x69, - 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, - 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x63, - 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x30, 0x01, 0x12, - 0x7b, 0x0a, 0x13, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, - 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2d, 0x69, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x42, 0xd0, 0x01, 0x0a, - 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, 0x73, - 0x74, 0x76, 0x31, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x41, 0x54, - 0xaa, 0x02, 0x11, 0x49, 0x6f, 0x2e, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x54, 0x65, 0x73, - 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x11, 0x49, 0x6f, 0x5c, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, - 0x5c, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x49, 0x6f, 0x5c, 0x41, 0x6b, - 0x75, 0x69, 0x74, 0x79, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x49, 0x6f, 0x3a, 0x3a, 0x41, - 0x6b, 0x75, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x6c, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, + 0x0a, 0x0f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x45, + 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, + 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, + 0x54, 0x45, 0x44, 0x10, 0x03, 0x32, 0x88, 0x05, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, + 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x7d, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, + 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x84, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, + 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, + 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, + 0x63, 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x13, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x2d, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, + 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, + 0x15, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2d, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x11, 0x44, 0x6f, 0x77, 0x6e, + 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2b, 0x2e, + 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, + 0x6f, 0x61, 0x64, 0x2d, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, + 0x42, 0xd0, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x6b, 0x75, 0x69, + 0x74, 0x79, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x76, 0x31, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x49, 0x41, 0x54, 0xaa, 0x02, 0x11, 0x49, 0x6f, 0x2e, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x11, 0x49, 0x6f, 0x5c, 0x41, 0x6b, + 0x75, 0x69, 0x74, 0x79, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x49, + 0x6f, 0x5c, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x56, 0x31, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x49, + 0x6f, 0x3a, 0x3a, 0x41, 0x6b, 0x75, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x3a, + 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -711,7 +758,7 @@ func file_testv1_test_proto_rawDescGZIP() []byte { } var file_testv1_test_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_testv1_test_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_testv1_test_proto_msgTypes = make([]protoimpl.MessageInfo, 14) var file_testv1_test_proto_goTypes = []interface{}{ (EventType)(0), // 0: io.akuity.test.v1.EventType (*InvitationMetadata)(nil), // 1: io.akuity.test.v1.InvitationMetadata @@ -724,15 +771,16 @@ var file_testv1_test_proto_goTypes = []interface{}{ (*TrackInvitationRequest)(nil), // 8: io.akuity.test.v1.TrackInvitationRequest (*TrackInvitationResponse)(nil), // 9: io.akuity.test.v1.TrackInvitationResponse (*DownloadInvitationsRequest)(nil), // 10: io.akuity.test.v1.DownloadInvitationsRequest - nil, // 11: io.akuity.test.v1.InvitationMetadata.RawEntry - nil, // 12: io.akuity.test.v1.Invitation.LabelsEntry - nil, // 13: io.akuity.test.v1.ListInvitationsQuery.LabelsEntry - (*httpbody.HttpBody)(nil), // 14: google.api.HttpBody + (*DownloadLargeFileRequest)(nil), // 11: io.akuity.test.v1.DownloadLargeFileRequest + nil, // 12: io.akuity.test.v1.InvitationMetadata.RawEntry + nil, // 13: io.akuity.test.v1.Invitation.LabelsEntry + nil, // 14: io.akuity.test.v1.ListInvitationsQuery.LabelsEntry + (*httpbody.HttpBody)(nil), // 15: google.api.HttpBody } var file_testv1_test_proto_depIdxs = []int32{ - 11, // 0: io.akuity.test.v1.InvitationMetadata.raw:type_name -> io.akuity.test.v1.InvitationMetadata.RawEntry - 12, // 1: io.akuity.test.v1.Invitation.labels:type_name -> io.akuity.test.v1.Invitation.LabelsEntry - 13, // 2: io.akuity.test.v1.ListInvitationsQuery.labels:type_name -> io.akuity.test.v1.ListInvitationsQuery.LabelsEntry + 12, // 0: io.akuity.test.v1.InvitationMetadata.raw:type_name -> io.akuity.test.v1.InvitationMetadata.RawEntry + 13, // 1: io.akuity.test.v1.Invitation.labels:type_name -> io.akuity.test.v1.Invitation.LabelsEntry + 14, // 2: io.akuity.test.v1.ListInvitationsQuery.labels:type_name -> io.akuity.test.v1.ListInvitationsQuery.LabelsEntry 3, // 3: io.akuity.test.v1.ListInvitationsRequest.query:type_name -> io.akuity.test.v1.ListInvitationsQuery 2, // 4: io.akuity.test.v1.ListInvitationsResponse.invitations:type_name -> io.akuity.test.v1.Invitation 0, // 5: io.akuity.test.v1.TrackInvitationRequest.type:type_name -> io.akuity.test.v1.EventType @@ -742,12 +790,14 @@ var file_testv1_test_proto_depIdxs = []int32{ 6, // 9: io.akuity.test.v1.TestService.SendInvitation:input_type -> io.akuity.test.v1.SendInvitationRequest 8, // 10: io.akuity.test.v1.TestService.TrackInvitation:input_type -> io.akuity.test.v1.TrackInvitationRequest 10, // 11: io.akuity.test.v1.TestService.DownloadInvitations:input_type -> io.akuity.test.v1.DownloadInvitationsRequest - 5, // 12: io.akuity.test.v1.TestService.ListInvitations:output_type -> io.akuity.test.v1.ListInvitationsResponse - 7, // 13: io.akuity.test.v1.TestService.SendInvitation:output_type -> io.akuity.test.v1.SendInvitationResponse - 9, // 14: io.akuity.test.v1.TestService.TrackInvitation:output_type -> io.akuity.test.v1.TrackInvitationResponse - 14, // 15: io.akuity.test.v1.TestService.DownloadInvitations:output_type -> google.api.HttpBody - 12, // [12:16] is the sub-list for method output_type - 8, // [8:12] is the sub-list for method input_type + 11, // 12: io.akuity.test.v1.TestService.DownloadLargeFile:input_type -> io.akuity.test.v1.DownloadLargeFileRequest + 5, // 13: io.akuity.test.v1.TestService.ListInvitations:output_type -> io.akuity.test.v1.ListInvitationsResponse + 7, // 14: io.akuity.test.v1.TestService.SendInvitation:output_type -> io.akuity.test.v1.SendInvitationResponse + 9, // 15: io.akuity.test.v1.TestService.TrackInvitation:output_type -> io.akuity.test.v1.TrackInvitationResponse + 15, // 16: io.akuity.test.v1.TestService.DownloadInvitations:output_type -> google.api.HttpBody + 15, // 17: io.akuity.test.v1.TestService.DownloadLargeFile:output_type -> google.api.HttpBody + 13, // [13:18] is the sub-list for method output_type + 8, // [8:13] is the sub-list for method input_type 8, // [8:8] is the sub-list for extension type_name 8, // [8:8] is the sub-list for extension extendee 0, // [0:8] is the sub-list for field type_name @@ -879,6 +929,18 @@ func file_testv1_test_proto_init() { return nil } } + file_testv1_test_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DownloadLargeFileRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_testv1_test_proto_msgTypes[7].OneofWrappers = []interface{}{} file_testv1_test_proto_msgTypes[9].OneofWrappers = []interface{}{} @@ -888,7 +950,7 @@ func file_testv1_test_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_testv1_test_proto_rawDesc, NumEnums: 1, - NumMessages: 13, + NumMessages: 14, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/test/gen/testv1/test.pb.gw.go b/internal/test/gen/testv1/test.pb.gw.go index f3f80e8..421d64f 100644 --- a/internal/test/gen/testv1/test.pb.gw.go +++ b/internal/test/gen/testv1/test.pb.gw.go @@ -174,6 +174,23 @@ func request_TestService_DownloadInvitations_0(ctx context.Context, marshaler ru } +func request_TestService_DownloadLargeFile_0(ctx context.Context, marshaler runtime.Marshaler, client TestServiceClient, req *http.Request, pathParams map[string]string) (TestService_DownloadLargeFileClient, runtime.ServerMetadata, error) { + var protoReq DownloadLargeFileRequest + var metadata runtime.ServerMetadata + + stream, err := client.DownloadLargeFile(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + // RegisterTestServiceHandlerServer registers the http handlers for service TestService to "mux". // UnaryRPC :call TestServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -244,6 +261,13 @@ func RegisterTestServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux return }) + mux.Handle("GET", pattern_TestService_DownloadLargeFile_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + return nil } @@ -373,6 +397,28 @@ func RegisterTestServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("GET", pattern_TestService_DownloadLargeFile_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/io.akuity.test.v1.TestService/DownloadLargeFile", runtime.WithHTTPPathPattern("/download-large-file")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_TestService_DownloadLargeFile_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_TestService_DownloadLargeFile_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -384,6 +430,8 @@ var ( pattern_TestService_TrackInvitation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"invitation", "id"}, "")) pattern_TestService_DownloadInvitations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"download-invitations"}, "")) + + pattern_TestService_DownloadLargeFile_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"download-large-file"}, "")) ) var ( @@ -394,4 +442,6 @@ var ( forward_TestService_TrackInvitation_0 = runtime.ForwardResponseStream forward_TestService_DownloadInvitations_0 = runtime.ForwardResponseStream + + forward_TestService_DownloadLargeFile_0 = runtime.ForwardResponseStream ) diff --git a/internal/test/gen/testv1/test_grpc.pb.go b/internal/test/gen/testv1/test_grpc.pb.go index b2a7ea8..cfdce1e 100644 --- a/internal/test/gen/testv1/test_grpc.pb.go +++ b/internal/test/gen/testv1/test_grpc.pb.go @@ -24,6 +24,7 @@ const ( TestService_SendInvitation_FullMethodName = "/io.akuity.test.v1.TestService/SendInvitation" TestService_TrackInvitation_FullMethodName = "/io.akuity.test.v1.TestService/TrackInvitation" TestService_DownloadInvitations_FullMethodName = "/io.akuity.test.v1.TestService/DownloadInvitations" + TestService_DownloadLargeFile_FullMethodName = "/io.akuity.test.v1.TestService/DownloadLargeFile" ) // TestServiceClient is the client API for TestService service. @@ -34,6 +35,7 @@ type TestServiceClient interface { SendInvitation(ctx context.Context, in *SendInvitationRequest, opts ...grpc.CallOption) (*SendInvitationResponse, error) TrackInvitation(ctx context.Context, in *TrackInvitationRequest, opts ...grpc.CallOption) (TestService_TrackInvitationClient, error) DownloadInvitations(ctx context.Context, in *DownloadInvitationsRequest, opts ...grpc.CallOption) (TestService_DownloadInvitationsClient, error) + DownloadLargeFile(ctx context.Context, in *DownloadLargeFileRequest, opts ...grpc.CallOption) (TestService_DownloadLargeFileClient, error) } type testServiceClient struct { @@ -126,6 +128,38 @@ func (x *testServiceDownloadInvitationsClient) Recv() (*httpbody.HttpBody, error return m, nil } +func (c *testServiceClient) DownloadLargeFile(ctx context.Context, in *DownloadLargeFileRequest, opts ...grpc.CallOption) (TestService_DownloadLargeFileClient, error) { + stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[2], TestService_DownloadLargeFile_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &testServiceDownloadLargeFileClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TestService_DownloadLargeFileClient interface { + Recv() (*httpbody.HttpBody, error) + grpc.ClientStream +} + +type testServiceDownloadLargeFileClient struct { + grpc.ClientStream +} + +func (x *testServiceDownloadLargeFileClient) Recv() (*httpbody.HttpBody, error) { + m := new(httpbody.HttpBody) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // TestServiceServer is the server API for TestService service. // All implementations must embed UnimplementedTestServiceServer // for forward compatibility @@ -134,6 +168,7 @@ type TestServiceServer interface { SendInvitation(context.Context, *SendInvitationRequest) (*SendInvitationResponse, error) TrackInvitation(*TrackInvitationRequest, TestService_TrackInvitationServer) error DownloadInvitations(*DownloadInvitationsRequest, TestService_DownloadInvitationsServer) error + DownloadLargeFile(*DownloadLargeFileRequest, TestService_DownloadLargeFileServer) error mustEmbedUnimplementedTestServiceServer() } @@ -153,6 +188,9 @@ func (UnimplementedTestServiceServer) TrackInvitation(*TrackInvitationRequest, T func (UnimplementedTestServiceServer) DownloadInvitations(*DownloadInvitationsRequest, TestService_DownloadInvitationsServer) error { return status.Errorf(codes.Unimplemented, "method DownloadInvitations not implemented") } +func (UnimplementedTestServiceServer) DownloadLargeFile(*DownloadLargeFileRequest, TestService_DownloadLargeFileServer) error { + return status.Errorf(codes.Unimplemented, "method DownloadLargeFile not implemented") +} func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {} // UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service. @@ -244,6 +282,27 @@ func (x *testServiceDownloadInvitationsServer) Send(m *httpbody.HttpBody) error return x.ServerStream.SendMsg(m) } +func _TestService_DownloadLargeFile_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(DownloadLargeFileRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServiceServer).DownloadLargeFile(m, &testServiceDownloadLargeFileServer{stream}) +} + +type TestService_DownloadLargeFileServer interface { + Send(*httpbody.HttpBody) error + grpc.ServerStream +} + +type testServiceDownloadLargeFileServer struct { + grpc.ServerStream +} + +func (x *testServiceDownloadLargeFileServer) Send(m *httpbody.HttpBody) error { + return x.ServerStream.SendMsg(m) +} + // TestService_ServiceDesc is the grpc.ServiceDesc for TestService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -271,6 +330,11 @@ var TestService_ServiceDesc = grpc.ServiceDesc{ Handler: _TestService_DownloadInvitations_Handler, ServerStreams: true, }, + { + StreamName: "DownloadLargeFile", + Handler: _TestService_DownloadLargeFile_Handler, + ServerStreams: true, + }, }, Metadata: "testv1/test.proto", } diff --git a/internal/test/server/server.go b/internal/test/server/server.go index 4ed0d27..477d5d7 100644 --- a/internal/test/server/server.go +++ b/internal/test/server/server.go @@ -1,11 +1,14 @@ package server import ( + _ "embed" + "bytes" "context" "encoding/base64" "time" + "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/bufbuild/protoyaml-go" "google.golang.org/genproto/googleapis/api/httpbody" @@ -76,3 +79,13 @@ func (s *testServiceServer) DownloadInvitations(req *testv1.DownloadInvitationsR } return nil } + +func (s *testServiceServer) DownloadLargeFile( + req *testv1.DownloadLargeFileRequest, + srv testv1.TestService_DownloadLargeFileServer, +) error { + return srv.Send(&httpbody.HttpBody{ + ContentType: "text/plain", + Data: []byte(assets.LargeFile), + }) +} diff --git a/pkg/grpc/gateway/request.go b/pkg/grpc/gateway/request.go index 4250695..12e9db5 100644 --- a/pkg/grpc/gateway/request.go +++ b/pkg/grpc/gateway/request.go @@ -1,7 +1,6 @@ package gateway import ( - "bufio" "bytes" "context" "encoding/json" @@ -164,31 +163,15 @@ func doHTTPStreamingRequest(ctx context.Context, c Client, req *resty.Request) ( contentType := res.Header().Get("Content-Type") body := res.RawBody() defer func() { _ = body.Close() }() - r := bufio.NewReader(body) - for { - var data bytes.Buffer - for { - line, isPrefix, err := r.ReadLine() - if err != nil { - if errors.Is(err, io.EOF) { - close(resCh) - return - } - errCh <- fmt.Errorf("read line: %w", err) - return - } - if _, err := data.Write(append(line, '\n')); err != nil { - errCh <- fmt.Errorf("write line: %w", err) - return - } - if !isPrefix { - break - } - } - resCh <- &httpbody.HttpBody{ - ContentType: contentType, - Data: data.Bytes(), - } + + var data bytes.Buffer + if _, err := io.Copy(&data, body); err != nil { + errCh <- fmt.Errorf("copy body: %w", err) + return + } + resCh <- &httpbody.HttpBody{ + ContentType: contentType, + Data: data.Bytes(), } }() return resCh, errCh, nil diff --git a/pkg/grpc/gateway/request_test.go b/pkg/grpc/gateway/request_test.go index 17eea85..b6c60f1 100644 --- a/pkg/grpc/gateway/request_test.go +++ b/pkg/grpc/gateway/request_test.go @@ -1,6 +1,8 @@ package gateway_test import ( + _ "embed" + "bytes" "context" "net" @@ -10,8 +12,10 @@ import ( "testing" "time" + "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/bufbuild/protoyaml-go" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/grpc" @@ -141,6 +145,32 @@ read: } } +func (s *RequestTestSuite) TestDownloadLargeFileRequest() { + ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) + defer cancel() + req := s.client.NewRequest(http.MethodGet, "/download-large-file") + resCh, errCh, err := gateway.DoStreamingRequest[httpbody.HttpBody](ctx, s.client, req) + s.Require().NoError(err) + var buf bytes.Buffer + +read: + for { + select { + case <-ctx.Done(): + break read + case err := <-errCh: + s.Require().NoError(err) + case data, ok := <-resCh: + if !ok { + break read + } + buf.Write(data.GetData()) + } + } + + require.Equal(s.T(), strings.TrimSpace(assets.LargeFile), strings.TrimSpace(buf.String())) +} + func (s *RequestTestSuite) TestDownloadRequest_Error() { ctx, cancel := context.WithTimeout(context.TODO(), 500*time.Millisecond) defer cancel() From 34d8940239e6a983998b8290364cd81efeb7680e Mon Sep 17 00:00:00 2001 From: Sunghoon Kang Date: Thu, 12 Sep 2024 17:14:57 +0900 Subject: [PATCH 2/3] fix: reformat Signed-off-by: Sunghoon Kang --- internal/test/server/server.go | 6 +++--- pkg/grpc/gateway/request_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/test/server/server.go b/internal/test/server/server.go index 477d5d7..e41ffe0 100644 --- a/internal/test/server/server.go +++ b/internal/test/server/server.go @@ -1,18 +1,18 @@ package server import ( - _ "embed" - "bytes" "context" "encoding/base64" "time" - "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/bufbuild/protoyaml-go" "google.golang.org/genproto/googleapis/api/httpbody" + "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/akuity/grpc-gateway-client/internal/test/gen/testv1" + + _ "embed" ) type testServiceServer struct { diff --git a/pkg/grpc/gateway/request_test.go b/pkg/grpc/gateway/request_test.go index b6c60f1..2bef504 100644 --- a/pkg/grpc/gateway/request_test.go +++ b/pkg/grpc/gateway/request_test.go @@ -1,8 +1,6 @@ package gateway_test import ( - _ "embed" - "bytes" "context" "net" @@ -12,7 +10,6 @@ import ( "testing" "time" - "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/bufbuild/protoyaml-go" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/stretchr/testify/require" @@ -25,9 +22,12 @@ import ( "google.golang.org/grpc/test/bufconn" "google.golang.org/protobuf/proto" + "github.com/akuity/grpc-gateway-client/internal/assets" "github.com/akuity/grpc-gateway-client/internal/test/gen/testv1" "github.com/akuity/grpc-gateway-client/internal/test/server" "github.com/akuity/grpc-gateway-client/pkg/grpc/gateway" + + _ "embed" ) type RequestTestSuite struct { From 2b10ffd2bd7afa3cabeea09b6407525295ca3157 Mon Sep 17 00:00:00 2001 From: Sunghoon Kang Date: Thu, 12 Sep 2024 17:19:49 +0900 Subject: [PATCH 3/3] fix: close channel after reading body Signed-off-by: Sunghoon Kang --- pkg/grpc/gateway/request.go | 1 + pkg/grpc/gateway/request_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/grpc/gateway/request.go b/pkg/grpc/gateway/request.go index 12e9db5..b2401af 100644 --- a/pkg/grpc/gateway/request.go +++ b/pkg/grpc/gateway/request.go @@ -173,6 +173,7 @@ func doHTTPStreamingRequest(ctx context.Context, c Client, req *resty.Request) ( ContentType: contentType, Data: data.Bytes(), } + close(resCh) }() return resCh, errCh, nil } diff --git a/pkg/grpc/gateway/request_test.go b/pkg/grpc/gateway/request_test.go index 2bef504..c16ff9e 100644 --- a/pkg/grpc/gateway/request_test.go +++ b/pkg/grpc/gateway/request_test.go @@ -168,6 +168,7 @@ read: } } + require.NoError(s.T(), ctx.Err()) require.Equal(s.T(), strings.TrimSpace(assets.LargeFile), strings.TrimSpace(buf.String())) }