From 92c2286174b8a05918015f40e2496d4b79ac3fb3 Mon Sep 17 00:00:00 2001 From: Paul-Christian Volkmer Date: Fri, 8 Mar 2024 11:16:00 +0100 Subject: [PATCH] Initial commit --- .gitignore | 5 + Cargo.toml | 41 +++ LICENSE.txt | 661 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 34 +++ dev-compose.yml | 18 ++ docs/etl.png | Bin 0 -> 76431 bytes src/main.rs | 130 ++++++++++ 7 files changed, 889 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 dev-compose.yml create mode 100644 docs/etl.png create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e57c52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/.idea +/target + +*.iml +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3d15138 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "bwhc-kafka-rest-proxy" +version = "0.1.0" +edition = "2021" +authors = ["Paul-Christian Volkmer "] +license = "AGPL-3.0" +description = "bwHC MTB-File REST Proxy für Kafka" + +# Dependencies + +[dependencies.log] +version = "0.4" + +[dependencies.simple-log] +version = "1.6" + +[dependencies.axum] +version = "0.7" + +[dependencies.tokio] +version = "1.36" +features = ["rt-multi-thread"] + +[dependencies.serde] +version = "1.0" +features = ["derive"] + +[dependencies.serde_json] +version = "1.0" + +[dependencies.rdkafka] +version = "0.36" +features = [ "cmake-build", "libz-static" ] + +[dependencies.uuid] +version = "1.7" +features = [ "v4" ] + +[dependencies.bwhc-dto] +git = "https://github.com/ccc-mf/bwhc-dto-rs" +branch = "master" \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a0d8eae --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# bwHC Kafka Rest Proxy + +bwHC MTB-File REST Proxy für Kafka + +### Einordnung innerhalb einer DNPM-ETL-Strecke + +Diese Anwendung erlaubt das Weiterleiten von REST Anfragen mit einem Request-Body und Inhalt eines bwHC MTB-Files +sowie `Content-Type` von `application/json` an einen Apache Kafka Cluster. + +Verwendung im Zusammenspiel mit https://github.com/CCC-MF/etl-processor + +![Modell DNPM-ETL-Strecke](docs/etl.png) + +## Konfiguration + +Die Anwendung lässt sich mit Umgebungsvariablen konfigurieren. + +* `APP_KAFKA_SERVERS`: Zu verwendende Kafka-Bootstrap-Server als kommagetrennte Liste +* `APP_KAFKA_TOPIC`: Zu verwendendes Topic zum Warten auf neue Anfragen. Standardwert: `etl-processor_input` + +## HTTP-Requests + +Die folgenden Endpunkte sind verfügbar: + +* **POST** `/mtbfile`: Senden eines MTB-Files +* **DELETE** `/mtbfile/:patient_id`: Löschen von Informationen zu dem Patienten + +Übermittelte MTB-Files müssen erforderliche Bestandteile beinhalten, ansonsten wird die Anfrage zurückgewiesen. + +Zum Löschen von Patienteninformationen wird intern ein MTB-File mit Consent-Status `REJECTED` erzeugt und weiter +geleitet. Hier ist kein Request-Body erforderlich. + +Bei Erfolg enthält die Antwort enthält im HTTP-Header `X-Request-Id` die Anfrage-ID, die auch im ETL-Prozessor verwendet +wird. \ No newline at end of file diff --git a/dev-compose.yml b/dev-compose.yml new file mode 100644 index 0000000..23da826 --- /dev/null +++ b/dev-compose.yml @@ -0,0 +1,18 @@ +services: + kafka: + image: bitnami/kafka + hostname: kafka + ports: + - "9092:9092" + - "9094:9094" + environment: + ALLOW_PLAINTEXT_LISTENER: "yes" + KAFKA_CFG_NODE_ID: "0" + KAFKA_CFG_PROCESS_ROLES: "controller,broker" + KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 + KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,EXTERNAL://localhost:9094 + KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT + KAFKA_CFG_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true" + KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093 + KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER \ No newline at end of file diff --git a/docs/etl.png b/docs/etl.png new file mode 100644 index 0000000000000000000000000000000000000000..73fddd5fac9f99a91849d968691e8ac7d81dfb3b GIT binary patch literal 76431 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 m4E*n&M^=y8*r2_lt!L$HX, +} + +#[tokio::main] +async fn main() { + let boostrap_servers = env::var("KAFKA_BOOTSTRAP_SERVERS").unwrap_or("kafka:9094".into()); + let dst_topic = env::var("APP_KAFKA_TOPIC").unwrap_or("etl-processor_input".into()); + + let producer: FutureProducer = ClientConfig::new() + .set("bootstrap.servers", boostrap_servers.as_str()) + .set("message.timeout.ms", "5000") + .create() + .expect("Producer creation error"); + + let app = Router::new() + .route("/mtbfile", post(handle_post)) + .route("/mtbfile/:patient_id", delete(handle_delete)) + .layer(Extension(producer)) + .layer(Extension(KafkaConfig { dst_topic })); + + let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); + axum::serve(listener, app).await.unwrap(); +} + +async fn handle_delete( + Path(patient_id): Path, + Extension(producer): Extension, + Extension(kafka_config): Extension, +) -> Response { + let delete_mtb_file = MtbFile::new_with_consent_rejected(&patient_id); + + match send_mtb_file(producer, &kafka_config.dst_topic, delete_mtb_file).await { + Ok(request_id) => success_response(&request_id), + _ => error_response(), + } +} + +async fn handle_post( + Extension(producer): Extension, + Extension(kafka_config): Extension, + Json(mtb_file): Json, +) -> Response { + match send_mtb_file(producer, &kafka_config.dst_topic, mtb_file).await { + Ok(request_id) => success_response(&request_id), + _ => error_response(), + } +} + +async fn send_mtb_file( + producer: FutureProducer, + topic: &str, + mtb_file: MtbFile, +) -> Result { + let request_id = Uuid::new_v4(); + + let record_key = RecordKey { + patient_id: mtb_file.patient.id.to_string(), + episode_id: if mtb_file.episode.id.is_empty() { + None + } else { + Some(mtb_file.episode.id.to_string()) + }, + }; + + let record_headers = OwnedHeaders::default().insert(Header { + key: "request_id", + value: Some(&request_id.to_string()), + }); + + let record_key = serde_json::to_string(&record_key).map_err(|_| ())?; + + match serde_json::to_string(&mtb_file) { + Ok(json) => { + producer + .send( + FutureRecord::to(topic) + .key(&record_key) + .headers(record_headers) + .payload(&json), + Duration::from_secs(1), + ) + .await + .map_err(|_| ()) + .map(|_| ())?; + Ok(request_id.to_string()) + } + Err(_) => Err(()), + } +} + +fn success_response(request_id: &str) -> Response { + Response::builder() + .status(StatusCode::ACCEPTED) + .header("X-Request-Id", request_id) + .body(Body::empty()) + .expect("response built") +} + +fn error_response() -> Response { + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(Body::empty()) + .expect("response built") +}