diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 0000000..4a36c32
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,18 @@
+name: Run tests
+run-name: ${{ github.event.pull_request.title }} (#${{ github.event.pull_request.number }}) - Run tests
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+ push:
+ branches:
+ - master
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-go@v4
+ with:
+ go-version: '1.20.2'
+ - name: Test
+ run: make test
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b5d7bd7..d48c759 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,90 +1,2 @@
-### JetBrains template
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-### Go template
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, built with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# Dependency directories (remove the comment below to include it)
-# vendor/
-
+.idea
+.vscode
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 02e3889..261eeb9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,201 @@
-MIT License
-
-Copyright (c) 2022 5GCoreNet
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d4231d4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+GOPATH := $(shell go env GOPATH)
+
+dependencies:
+ echo "Installing dependencies"
+ go install github.com/golang/mock/mockgen@v1.6.0
+ go mod download
+
+mock-gen: dependencies
+ echo "Generating mock files"
+ PATH=$(PATH):$(GOPATH)/bin go generate ./...
+
+test: mock-gen
+ echo "Running tests"
+ go test -v ./...
+
+.PHONY: mock-gen
diff --git a/README.md b/README.md
index 59011a6..62b2e15 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,26 @@
# 5GCoreNetSDK
-[](https://github.com/5GCoreNet/5GCoreNetSDK)
-[](https://github.com/5GCoreNet/5GCoreNetSDK/blob/main/LICENSE)
-[](https://github.com/5GCoreNet/5GCoreNetSDK)
+[](https://pkg.go.dev/github.com/5GCoreNet/5GCoreNetSDK)
+[](https://goreportcard.com/report/github.com/5GCoreNet/5GCoreNetSDK)
+[](LICENSE)
+
+> At this moment, this SDK is in development. It is not ready for production use.
+> Refers to the [Roadmap](#roadmap) section for more information on what has been done.
+>
+> See the [Contributing](#contributing) section if you would like to help make it better.
+
-
+
-> At this moment, this SDK is in development. It is not ready for production use.
-> Refers to the [Roadmap](#roadmap) section for more information on what has been done.
->
-> See the [Contributing](#contributing) section if you would like to help
-> make it better.
-
-5GCoreNetSDK is an open source project that provides a set of APIs to access or provide services in 5G Core Network. The APIs are based on the 3GPP specifications and are implemented in Golang.
+5GCoreNetSDK is an open source project that provides a set of APIs to access or expose a Network Function (NF) in 5G Core Network.
+The APIs are based on the 3GPP specifications and are implemented in Golang.
-Under the hood, the SDK exposes through a RESTful API the Network Function you've built, according to the standard. The RESTful API is implemented using [Gin](https://github.com/gin-gonic/gin) framework.
+Under the hood, the SDK exposes the standard HTTP RESTful API for the Network Function you've built.
+The RESTful APIs are implemented using [Gin](https://github.com/gin-gonic/gin) framework.
-At the moment, the APIs are implemented for the release 18 of the 3GPP specifications.
+The SDK follows the R18 3GPP specifications.
## Getting Started
@@ -26,19 +28,37 @@ At the moment, the APIs are implemented for the release 18 of the 3GPP specifica
go get github.com/5GCoreNet/5GCoreNetSDK
```
+## Features
-## Contributing
-Feel free to contribute to this project. You can do it by:
-- Reporting bugs
-- Suggesting new features
-- Implementing new features
-- Fixing bugs
-- Improving documentation
-- ...
-
-## License
-Licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
+- Simple and easy to use, just implement the interface you need, and you are ready to go
+- Support for both Server and Client mode
+- Follows the 3GPP specifications out of the box (R18)
+- C compatible thanks to [cgo](https://golang.org/cmd/cgo/)
+- Fully open source and free to use, modify, and distribute under the terms of the [Apache 2.0 license](LICENSE)
## Roadmap
-TBD
+As 5GCoreNetSDK is still in development, the following table is the roadmap representing what has been done and what is still to do.
+The following table shows the status of the APIs and the order in which they will be implemented. If you want to see a specific API implemented,
+you can open an issue (or you can implement it and open a pull request).
+
+Network Function | API | Status | Comments | Documentation
+---------------- |------|-----------------|-----------------------------------------------------------------------------------------| -------------
+LMF | NLMF | In progress | NLMF is the first API proposal and is considered as a PoC. NLMF might change in future. | [Link](fivegc/nlmf/examples/main.go)
+NRF | NNRF | Not implemented | |
+AMF | NAMF | Not implemented | |
+SMF | NSMF | Not implemented | |
+UDM | NUDM | Not implemented | |
+UDR | NUDR | Not implemented | |
+AUSF | NAUSF | Not implemented | |
+PCF | NPCF | Not implemented | |
+NSSF | NNSSF | Not implemented | |
+N3IWF | NN3IWF | Not implemented | |
+UPF | NUPF | Not implemented | |
+
+
+> Note that API is considered implemented if it is implemented in the SDK in Server and Client mode and if it is tested and documented.
+
+## Contributing
+
+Contributions are welcome! Please read the [Contributing Guide](docs/CONTRIBUTING.md) for more information.
\ No newline at end of file
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 100644
index 0000000..c64997a
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1,106 @@
+# Contributing
+
+When contributing to this repository, please ensure that your Pull Request is linked to an issue,
+and that the issue is tagged with the appropriate labels (e.g. bug, enhancement, etc.). This will
+help us to keep track of the changes and discuss them.
+
+Please note we have a code of conduct, please follow it in all your interactions with the project.
+
+If you want to contribute to 5GCoreNetSDK, please make sure that your code follows principles defined in [Design Principles](design-principles.md).
+## Pull Request Process
+
+Firstly, thank you for contributing to this repository. Please ensure that you gather the following requirements to contribute:
+
+1. Ensure that the Pull Request is linked to an issue.
+2. Ensure that the issue is tagged with the appropriate labels (e.g. bug, enhancement, etc.) and prefix your Pull Request with the domain of the issue and NF impacted (e.g. `bugfix/nlmf`, `enhancement/nlmf`, etc.).
+3. Ensure that you only include one commit in your Pull Request. If you have multiple commits, please squash them into one commit.
+4. Ensure you sign your commits. See [Signing your commits](#signing-your-commits) for more information.
+5. Ensure that you have updated the documentation and the tests to reflect your changes.
+6. Run the tests to ensure that your changes do not break any existing tests.
+7. Ensure that your code is formatted using `gofmt` and linted using `golint`.
+8. Prepare a Pull Request with the following information:
+ * A description of the changes you have made.
+ * A link to the issue you are fixing.
+
+### Signing your commits
+
+To sign your commits, just add the `-s` flag when you commit. This will add a `Signed-off-by` line to your commit message. For example:
+
+```bash
+git commit -s -m "This is my commit message"
+```
+
+## Code of Conduct
+
+### Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+### Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+### Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+### Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+### Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+### Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file
diff --git a/docs/design-principles.md b/docs/design-principles.md
new file mode 100644
index 0000000..387651c
--- /dev/null
+++ b/docs/design-principles.md
@@ -0,0 +1,115 @@
+# Design principals
+
+As 5GCoreNetSDK aims to be a simple and easy to use SDK, we have defined some design principals that we want to follow.
+
+If you want to contribute to 5GCoreNetSDK, please make sure that your code follows these principals.
+
+## Simple and easy to use
+
+This is the main goal of 5GCoreNetSDK. We want to provide a simple and easy to use SDK to build 5G Core Network NFs following the R18 3GPP specifications.
+
+Indeed, some 3GPP specifications are very complex and hard to understand. We want to make it easy to use the 3GPP specifications in code.
+
+## Interface based
+
+5GCoreNetSDK is based on interfaces. This means that you need to implement the interfaces. To do so, you just need to
+create a struct that implements the interface and that's it.
+
+This is very useful because it allows you to provide your own implementation of the Network Functions without bothering about the 3GPP specifications.
+
+Plus, it makes it easy to test your code, because you can mock the interfaces you need.
+
+So every Network Function connectivity layer must be based on an interface.
+
+Let's take an example, consider we want to implement the `Foo` endpoint.
+
+```go
+package foo
+
+import (
+ "context"
+ "github.com/5GCore/5GCoreNetSDK/fivegc"
+)
+
+type Foo interface {
+ fivegc.CommonInterface
+ Foo(context.Context, string) string, ProblemDetails, fivegc.RedirectResponse, FooStatusCode
+}
+```
+
+This interface is composed of the `CommonInterface` interface, which is the interface that every endpoint must implement.
+
+`CommonInterface` is here to provide a common interface wrapping error handling (maybe we will add more stuff in the future).
+
+Then, we have the `Foo` method, which is the method that will be called when a request is sent to the `Foo` endpoint.
+
+And that's it, you have implemented the `Foo` endpoint. Not so hard, right?
+
+## Client flow
+Interfaces are used for the server part, whereas the client part is following a more classical flow.
+
+Client must follow the following flow to send a request to a service:
+
+1 - Create a new client
+2 - Create a new query
+3 - Fill the query with the parameters
+3 - Execute the query
+
+```go
+// Create a new client
+client := client.NewClient(cfg)
+// Client can be used to create a new query
+query := client.NetworkFunctionEndpoint(ctx)
+// Query can be used to fill the parameters
+query = query.Paramaters(model)
+// Query can be used to send a request to the server
+response, err := client.NetworkFunctionEndpointExecute(query)
+```
+
+This flow is very simple and easy to use. It is also very easy to test, because you can mock the client and the query,
+thus we decided to follow this flow for the client part.
+
+## Error handling
+
+As in 3GPP specifications, errors are handled using the `ProblemDetails` struct.
+
+Unmarshalling errors must be handled using the `ProblemDetails` struct as well. This struct is used to provide additional information in an error response.
+That's why we decided to add na `Error()` method to all the interfaces by using the `CommonInterface` interface.
+
+```go
+type CommonInterface interface {
+ // Error returns a problem details, it is used to handle errors when unmarshalling the request.
+ Error(ctx context.Context, err error) openapicommon.ProblemDetails
+}
+```
+Error is called when an error occurs during the unmarshalling of the request. It is used to provide additional information about the error.
+
+Thus, SDK users can handle by themselves the errors without effort.
+
+## Mocking
+
+Every interface implemented must be mocked. This is a very elegant way to provide user a way to test their code.
+
+In order to do so, we use the `mockgen` library. This library allows us to generate mocks from interfaces.
+
+Let's take an example, consider we want to mock the `Foo` interface.
+
+```go
+package mock // located under foo/mock
+
+//go:generate mockgen -source=../foo.go -destination=foo.go -package=mock
+```
+
+This command will generate a `foo.go` file under the `foo/mock` package. This file will contain a mocked `Foo` interface.
+
+## Testing
+
+Every endpoint must be tested against the 3GPP specifications. Thus, we can ensure that our code is compliant with the 3GPP specifications and that we are not breaking anything.
+
+## Documentation
+
+Every endpoint must be documented. This is very important because it allows users to understand how to use the endpoint.
+
+You have to use GoDoc format to document your code. This is very easy to use, and it is very useful. You can find more information about GoDoc [here](https://blog.golang.org/godoc).
+
+Plus, you can add an example of how to use the endpoint. This is very useful because it allows users to better understand how to use the endpoint.
\ No newline at end of file
diff --git a/docs/images/logo_no_bg.png b/docs/images/logo_no_bg.png
new file mode 100644
index 0000000..ab8141a
Binary files /dev/null and b/docs/images/logo_no_bg.png differ
diff --git a/docs/images/logo_white_bg.png b/docs/images/logo_white_bg.png
new file mode 100644
index 0000000..a0fa941
Binary files /dev/null and b/docs/images/logo_white_bg.png differ
diff --git a/docs/philosophy.md b/docs/philosophy.md
new file mode 100644
index 0000000..10abe18
--- /dev/null
+++ b/docs/philosophy.md
@@ -0,0 +1,47 @@
+# Philosophy of 5GCoreNetSDK
+
+This document describes the philosophy of 5GCoreNetSDK and why we decided to start this project.
+
+Feel free to contribute to this document by creating a pull request or by opening an issue.
+
+## Motivation
+5G Core Network is a complex network. It is composed of many Network Functions (NFs) that communicate with each other.
+The 3GPP specifications are very complex and hard to understand. Thus, it is hard to develop inside this network.
+
+Many projects provide already built Network Functions (NFs) that you can use, but if you want to build your own Network Function (NF),
+you need to implement the 3GPP specifications by yourself. This is very time-consuming and hard to do.
+
+Through this project, we want to provide a simple and easy to use SDK to build 5G Core Network NFs following the R18 3GPP specifications.
+
+The SDK is designed to be simple and easy to use, just implement the interface you need, and you are ready to go.
+
+
+## What 5GCoreNetSDK is
+
+5GCoreNetSDK is a developer centric SDK to build 5G Core Network Functions (NFs) following the R18 3GPP specifications.
+
+It is written in [Golang](#why-golang) and is based on interfaces. This means that you only need to implement the interfaces you need to connect your Network Function (NF) to the 5G Core Network.
+
+Plus, thanks to the interfaces, even if you don't know the 3GPP specifications nor 5G Core design, you can easily develop a Network Function (NF) that will work with the 5G Core Network.
+
+## What 5GCoreNetSDK is not
+
+5GCoreNetSDK is not a :
+
+* Network Function (NF) implementation.
+* 5G Core Network implementation.
+* 5G Core Network simulator.
+* 5G Core Network emulator.
+
+The goal of 5GCoreNetSDK is to provide a simply to use connectivity layer inside the 5G Core Network.
+
+## Technical choices
+
+### Why Golang?
+
+As you may know, many Network Functions (NFs) are implemented in C. This is because C is a very fast and secure language.
+However, C is not easy to use. It is not easy to learn, and it is not easy to write code in C making it hard to maintain.
+
+Projects like [Free5GC](https://www.free5gc.org/) decided to use Golang to implement their Network Functions (NFs). This is because Golang is a modern programming language that is easy to learn and use. It is also a compiled language, which means that it is fast and
+secure. Golang is also a C compatible language, which means that you can use C libraries in your Golang code, thus
+you can easily import your C code to use it with 5GCoreNetSDK.
diff --git a/fivegc/helper.go b/fivegc/helper.go
new file mode 100644
index 0000000..78a5fb9
--- /dev/null
+++ b/fivegc/helper.go
@@ -0,0 +1,33 @@
+package fivegc
+
+func ToInt(i int) *int {
+ return &i
+}
+
+func ToInt64(i int64) *int64 {
+ return &i
+}
+
+func ToInt32(i int32) *int32 {
+ return &i
+}
+
+func ToInt16(i int16) *int16 {
+ return &i
+}
+
+func ToInt8(i int8) *int8 {
+ return &i
+}
+
+func ToFloat64(f float64) *float64 {
+ return &f
+}
+
+func ToFloat32(f float32) *float32 {
+ return &f
+}
+
+func ToString(s string) *string {
+ return &s
+}
diff --git a/fivegc/nlmf/broadcast.go b/fivegc/nlmf/broadcast.go
index d1f0cac..38e9a0c 100644
--- a/fivegc/nlmf/broadcast.go
+++ b/fivegc/nlmf/broadcast.go
@@ -4,71 +4,84 @@ import (
"context"
"github.com/5GCoreNet/5GCoreNetSDK/fivegc"
"github.com/5GCoreNet/5GCoreNetSDK/internal/header"
- openapinlmfbroadcastclient "github.com/5GCoreNet/client-openapi/Nlmf_Broadcast"
- openapinlmfbroadcastserver "github.com/5GCoreNet/server-openapi/Nlmf_Broadcast"
+ openapicommon "github.com/5GCoreNet/openapi/openapi_CommonData"
+ openapinlmfbroadcast "github.com/5GCoreNet/openapi/openapi_Nlmf_Broadcast"
"github.com/gin-gonic/gin"
)
+const (
+ broadcastRouterGroup = "/nlmf-broadcast/v1"
+ cypherKeyEndpoint = "/cipher-key-data"
+)
+
+// Broadcast is the interface that wraps the NLMF Broadcast service.
type Broadcast interface {
- // Error returns a problem details, it is used to handle errors when unmarshalling the request.
- Error(ctx context.Context, err error) openapinlmfbroadcastserver.ProblemDetails
- // CipherKeyData returns a cipher response data, a problem details, a redirect response and a status code.
- CipherKeyData(context.Context, openapinlmfbroadcastserver.CipherRequestData) (openapinlmfbroadcastserver.CipherResponseData, openapinlmfbroadcastserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
+ fivegc.CommonInterface
+ CipherKeyData(context.Context, openapinlmfbroadcast.CipherRequestData) (openapinlmfbroadcast.CipherResponseData, openapicommon.ProblemDetails, fivegc.RedirectResponse, CypherResponseStatusCode)
}
+type CypherResponseStatusCode fivegc.StatusCode
+
+const (
+ // CypherResponseStatusCodeOK is the status code for a successful response.
+ CypherResponseStatusCodeOK CypherResponseStatusCode = CypherResponseStatusCode(fivegc.StatusOK)
+ CypherResponseStatusTemporaryRedirect CypherResponseStatusCode = CypherResponseStatusCode(fivegc.StatusTemporaryRedirect)
+ CypherResponseStatusPermanentRedirect CypherResponseStatusCode = CypherResponseStatusCode(fivegc.StatusPermanentRedirect)
+)
+
func attachBroadcastHandler(router *gin.RouterGroup, b Broadcast) {
- group := router.Group("/nlmf-broadcast/v1")
+ group := router.Group(broadcastRouterGroup)
{
- group.POST("/cipher-key-data", func(c *gin.Context) {
- var req openapinlmfbroadcastserver.CipherRequestData
+ group.POST(cypherKeyEndpoint, func(c *gin.Context) {
+ var req openapinlmfbroadcast.CipherRequestData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := b.Error(c, err)
- c.JSON(int(problemDetails.Status), problemDetails)
+ c.JSON(int(*problemDetails.Status), problemDetails)
return
}
res, problemDetails, redirectResponse, status := b.CipherKeyData(c, req)
switch status {
- case fivegc.StatusOK:
- c.JSON(status.ToInt(), res)
- case fivegc.StatusTemporaryRedirect:
+ case CypherResponseStatusCodeOK:
+ c.JSON(int(status), res)
+ case CypherResponseStatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
- case fivegc.StatusPermanentRedirect:
+ c.JSON(int(status), redirectResponse)
+ case CypherResponseStatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
+ c.JSON(int(status), redirectResponse)
default:
- c.JSON(status.ToInt(), problemDetails)
+ c.JSON(int(status), problemDetails)
}
return
})
}
}
-// BroadcastClient is a client for the Nlmf_Broadcast service.
+// BroadcastClient is a client for the NLMF Broadcast service.
type BroadcastClient struct {
- client *openapinlmfbroadcastclient.APIClient
+ client *openapinlmfbroadcast.APIClient
}
-// NewBroadcastClient creates a new client for the Nlmf_Broadcast service.
+// NewBroadcastClient creates a new client for the NLMF Broadcast service.
func NewBroadcastClient(cfg fivegc.ClientConfiguration) *BroadcastClient {
- openapiCfg := &openapinlmfbroadcastclient.Configuration{
+ openapiCfg := &openapinlmfbroadcast.Configuration{
Host: cfg.Host,
Scheme: cfg.Scheme,
DefaultHeader: cfg.DefaultHeader,
UserAgent: cfg.UserAgent,
Debug: cfg.Debug,
- Servers: []openapinlmfbroadcastclient.ServerConfiguration{},
- OperationServers: make(map[string]openapinlmfbroadcastclient.ServerConfigurations),
+ Servers: []openapinlmfbroadcast.ServerConfiguration{},
+ OperationServers: make(map[string]openapinlmfbroadcast.ServerConfigurations),
HTTPClient: cfg.HTTPClient,
}
for _, server := range cfg.Servers {
- openapiServer := openapinlmfbroadcastclient.ServerConfiguration{
+ openapiServer := openapinlmfbroadcast.ServerConfiguration{
URL: server.URL,
Description: server.Description,
- Variables: make(map[string]openapinlmfbroadcastclient.ServerVariable),
+ Variables: make(map[string]openapinlmfbroadcast.ServerVariable),
}
for name, variable := range server.Variables {
- openapiServer.Variables[name] = openapinlmfbroadcastclient.ServerVariable{
+ openapiServer.Variables[name] = openapinlmfbroadcast.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
@@ -77,15 +90,15 @@ func NewBroadcastClient(cfg fivegc.ClientConfiguration) *BroadcastClient {
openapiCfg.Servers = append(openapiCfg.Servers, openapiServer)
}
for name, servers := range cfg.OperationServers {
- openapiServers := make(openapinlmfbroadcastclient.ServerConfigurations, len(servers))
+ openapiServers := make(openapinlmfbroadcast.ServerConfigurations, len(servers))
for i, server := range servers {
- openapiServers[i] = openapinlmfbroadcastclient.ServerConfiguration{
+ openapiServers[i] = openapinlmfbroadcast.ServerConfiguration{
URL: server.URL,
Description: server.Description,
- Variables: make(map[string]openapinlmfbroadcastclient.ServerVariable),
+ Variables: make(map[string]openapinlmfbroadcast.ServerVariable),
}
for name, variable := range server.Variables {
- openapiServers[i].Variables[name] = openapinlmfbroadcastclient.ServerVariable{
+ openapiServers[i].Variables[name] = openapinlmfbroadcast.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
@@ -95,17 +108,17 @@ func NewBroadcastClient(cfg fivegc.ClientConfiguration) *BroadcastClient {
openapiCfg.OperationServers[name] = openapiServers
}
return &BroadcastClient{
- client: openapinlmfbroadcastclient.NewAPIClient(openapiCfg),
+ client: openapinlmfbroadcast.NewAPIClient(openapiCfg),
}
}
// CipheringKeyData returns a cipher request.
-func (c *BroadcastClient) CipheringKeyData(ctx context.Context) openapinlmfbroadcastclient.ApiCipheringKeyDataRequest {
+func (c *BroadcastClient) CipheringKeyData(ctx context.Context) openapinlmfbroadcast.ApiCipheringKeyDataRequest {
return c.client.RequestCipheringKeyDataApi.CipheringKeyData(ctx)
}
// CipheringKeyDataExecute executes a cipher request.
-func (c *BroadcastClient) CipheringKeyDataExecute(r openapinlmfbroadcastclient.ApiCipheringKeyDataRequest) (*openapinlmfbroadcastclient.CipherResponseData, error) {
+func (c *BroadcastClient) CipheringKeyDataExecute(r openapinlmfbroadcast.ApiCipheringKeyDataRequest) (*openapinlmfbroadcast.CipherResponseData, error) {
resp, _, err := r.Execute()
return resp, err
}
diff --git a/fivegc/nlmf/client.go b/fivegc/nlmf/client.go
new file mode 100644
index 0000000..dc9b906
--- /dev/null
+++ b/fivegc/nlmf/client.go
@@ -0,0 +1,16 @@
+package nlmf
+
+import "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
+
+type Client struct {
+ *BroadcastClient
+ *LocationClient
+}
+
+// NewClient returns a new client for an NLMF service.
+func NewClient(config fivegc.ClientConfiguration) *Client {
+ return &Client{
+ BroadcastClient: NewBroadcastClient(config),
+ LocationClient: NewLocationClient(config),
+ }
+}
diff --git a/fivegc/nlmf/examples/main.go b/fivegc/nlmf/examples/main.go
new file mode 100644
index 0000000..5d17985
--- /dev/null
+++ b/fivegc/nlmf/examples/main.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "context"
+ "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
+ "github.com/5GCoreNet/5GCoreNetSDK/fivegc/nlmf"
+ openapicommon "github.com/5GCoreNet/openapi/openapi_CommonData"
+ nlmfbroadcast "github.com/5GCoreNet/openapi/openapi_Nlmf_Broadcast"
+ "log"
+)
+
+type MyBroadcast struct {
+}
+
+func (m MyBroadcast) Error(ctx context.Context, err error) openapicommon.ProblemDetails {
+ return openapicommon.ProblemDetails{
+ Type: fivegc.ToString("error"),
+ Title: fivegc.ToString("error"),
+ Status: fivegc.ToInt32(int32(fivegc.StatusInternalServerError)),
+ Detail: fivegc.ToString(err.Error()),
+ Instance: fivegc.ToString("fake_instance"),
+ Cause: fivegc.ToString("unknown"),
+ InvalidParams: nil,
+ SupportedFeatures: fivegc.ToString(""),
+ AccessTokenError: &openapicommon.AccessTokenErr{},
+ AccessTokenRequest: &openapicommon.AccessTokenReq{},
+ NrfId: fivegc.ToString("1234567890"),
+ }
+}
+
+func (m MyBroadcast) CipherKeyData(ctx context.Context, data nlmfbroadcast.CipherRequestData) (nlmfbroadcast.CipherResponseData, openapicommon.ProblemDetails, fivegc.RedirectResponse, nlmf.CypherResponseStatusCode) {
+ // Your code here ...
+ return nlmfbroadcast.CipherResponseData{}, openapicommon.ProblemDetails{}, fivegc.RedirectResponse{}, nlmf.CypherResponseStatusCodeOK
+}
+
+func main() {
+ m := MyBroadcast{}
+ nlmfServer := nlmf.NewServer(":8080", "/v1/", log.Default())
+ nlmfServer.AttachBroadcast(m)
+ nlmfServer.Start()
+ // Your code here ...
+ nlmfServer.Stop()
+}
diff --git a/fivegc/nlmf/location.go b/fivegc/nlmf/location.go
index afe05b2..71edc12 100644
--- a/fivegc/nlmf/location.go
+++ b/fivegc/nlmf/location.go
@@ -4,122 +4,156 @@ import (
"context"
"github.com/5GCoreNet/5GCoreNetSDK/fivegc"
"github.com/5GCoreNet/5GCoreNetSDK/internal/header"
- openapinlmflocationclient "github.com/5GCoreNet/client-openapi/Nlmf_Location"
- openapinlmflocationserver "github.com/5GCoreNet/server-openapi/Nlmf_Location"
+ openapicommon "github.com/5GCoreNet/openapi/openapi_CommonData"
+ nlmfocation "github.com/5GCoreNet/openapi/openapi_Nlmf_Location"
"github.com/gin-gonic/gin"
"net/http"
)
+const (
+ locationRouterGroup = "/nlmf-loc/v1"
+ cancelLocationEndpoint = "/cancel-location"
+ determineLocationEndpoint = "/determine-location"
+ locationContextTransferEndpoint = "/location-context-transfer"
+)
+
type Location interface {
- // Error returns a problem details, it is used to handle errors when unmarshalling the request.
- Error(ctx context.Context, err error) openapinlmflocationserver.ProblemDetails
+ fivegc.CommonInterface
// CancelLocation cancels a location request.
- CancelLocation(context.Context, openapinlmflocationserver.CancelLocData) (openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
+ CancelLocation(context.Context, nlmfocation.CancelLocData) (openapicommon.ProblemDetails, fivegc.RedirectResponse, CancelLocationStatusCode)
// DetermineLocation determines the location of a UE.
- DetermineLocation(context.Context, openapinlmflocationserver.InputData) (openapinlmflocationserver.LocationData, openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
+ DetermineLocation(context.Context, nlmfocation.InputData) (nlmfocation.LocationData, openapicommon.ProblemDetails, fivegc.RedirectResponse, DetermineLocationStatusCode)
// LocationContextTransfer transfers the location context of a UE.
- LocationContextTransfer(context.Context, openapinlmflocationserver.LocContextData) (openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
+ LocationContextTransfer(context.Context, nlmfocation.LocContextData) (openapicommon.ProblemDetails, fivegc.RedirectResponse, LocationContextTransferStatusCode)
}
+type CancelLocationStatusCode fivegc.StatusCode
+
+const (
+ // CancelLocationStatusNoContent is the status code for the response when the location request is successfully cancelled.
+ CancelLocationStatusNoContent CancelLocationStatusCode = CancelLocationStatusCode(fivegc.StatusNoContent)
+ CancelLocationStatusTemporaryRedirect CancelLocationStatusCode = CancelLocationStatusCode(fivegc.StatusTemporaryRedirect)
+ CancelLocationStatusPermanentRedirect CancelLocationStatusCode = CancelLocationStatusCode(fivegc.StatusPermanentRedirect)
+)
+
+type DetermineLocationStatusCode fivegc.StatusCode
+
+const (
+ // DetermineLocationStatusOK is the status code for a successful response.
+ DetermineLocationStatusOK DetermineLocationStatusCode = DetermineLocationStatusCode(fivegc.StatusOK)
+ DetermineLocationStatusNoContent DetermineLocationStatusCode = DetermineLocationStatusCode(fivegc.StatusNoContent)
+ DetermineLocationStatusTemporaryRedirect DetermineLocationStatusCode = DetermineLocationStatusCode(fivegc.StatusTemporaryRedirect)
+ DetermineLocationStatusPermanentRedirect DetermineLocationStatusCode = DetermineLocationStatusCode(fivegc.StatusPermanentRedirect)
+)
+
+type LocationContextTransferStatusCode fivegc.StatusCode
+
+const (
+ // LocationContextTransferStatusNoContent is the status code for the response when the location context transfer is successful.
+ LocationContextTransferStatusNoContent LocationContextTransferStatusCode = LocationContextTransferStatusCode(fivegc.StatusNoContent)
+ LocationContextTransferStatusTemporaryRedirect LocationContextTransferStatusCode = LocationContextTransferStatusCode(fivegc.StatusTemporaryRedirect)
+ LocationContextTransferStatusPermanentRedirect LocationContextTransferStatusCode = LocationContextTransferStatusCode(fivegc.StatusPermanentRedirect)
+)
+
func attachLocationHandler(router *gin.RouterGroup, l Location) {
- group := router.Group("/nlmf-loc/v1")
+ group := router.Group(locationRouterGroup)
{
- group.POST("/cancel-location", func(c *gin.Context) {
- var req openapinlmflocationserver.CancelLocData
+ group.POST(cancelLocationEndpoint, func(c *gin.Context) {
+ var req nlmfocation.CancelLocData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
- c.JSON(int(problemDetails.Status), problemDetails)
+ c.JSON(int(*problemDetails.Status), problemDetails)
return
}
problemDetails, redirectResponse, status := l.CancelLocation(c, req)
switch status {
- case fivegc.StatusNoContent:
- c.JSON(status.ToInt(), nil)
- case fivegc.StatusTemporaryRedirect:
+ case CancelLocationStatusNoContent:
+ c.JSON(int(status), nil)
+ case CancelLocationStatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
- case fivegc.StatusPermanentRedirect:
+ c.JSON(int(status), redirectResponse)
+ case CancelLocationStatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
+ c.JSON(int(status), redirectResponse)
default:
- c.JSON(status.ToInt(), problemDetails)
+ c.JSON(int(status), problemDetails)
}
return
})
- group.POST("/determine-location", func(c *gin.Context) {
- var req openapinlmflocationserver.InputData
+ group.POST(determineLocationEndpoint, func(c *gin.Context) {
+ var req nlmfocation.InputData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
- c.JSON(int(problemDetails.Status), problemDetails)
+ c.JSON(int(*problemDetails.Status), problemDetails)
return
}
res, problemDetails, redirectResponse, status := l.DetermineLocation(c, req)
switch status {
- case fivegc.StatusOK:
- c.JSON(status.ToInt(), res)
- case fivegc.StatusNoContent:
- c.JSON(status.ToInt(), nil)
- case fivegc.StatusTemporaryRedirect:
+ case DetermineLocationStatusOK:
+ c.JSON(int(status), res)
+ case DetermineLocationStatusNoContent:
+ c.JSON(int(status), nil)
+ case DetermineLocationStatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
- case fivegc.StatusPermanentRedirect:
+ c.JSON(int(status), redirectResponse)
+ case DetermineLocationStatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
+ c.JSON(int(status), redirectResponse)
default:
- c.JSON(status.ToInt(), problemDetails)
+ c.JSON(int(status), problemDetails)
}
return
})
- group.POST("/location-context-transfer", func(c *gin.Context) {
- var req openapinlmflocationserver.LocContextData
+ group.POST(locationContextTransferEndpoint, func(c *gin.Context) {
+ var req nlmfocation.LocContextData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
- c.JSON(int(problemDetails.Status), problemDetails)
+ c.JSON(int(*problemDetails.Status), problemDetails)
return
}
problemDetails, redirectResponse, status := l.LocationContextTransfer(c, req)
switch status {
- case fivegc.StatusNoContent:
- c.JSON(status.ToInt(), nil)
- case fivegc.StatusTemporaryRedirect:
+ case LocationContextTransferStatusNoContent:
+ c.JSON(int(status), nil)
+ case LocationContextTransferStatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
- case fivegc.StatusPermanentRedirect:
+ c.JSON(int(status), redirectResponse)
+ case LocationContextTransferStatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
- c.JSON(status.ToInt(), redirectResponse)
+ c.JSON(int(status), redirectResponse)
default:
- c.JSON(status.ToInt(), problemDetails)
+ c.JSON(int(status), problemDetails)
}
return
})
}
}
-// LocationClient is a client for the Nlmf_location service.
+// LocationClient is a client for the NLMF Location service.
type LocationClient struct {
- client *openapinlmflocationclient.APIClient
+ client *nlmfocation.APIClient
}
-// NewLocationClient creates a new client for the Nlmf_location service.
+// NewLocationClient creates a new client for the NLMF Location service.
func NewLocationClient(cfg fivegc.ClientConfiguration) *LocationClient {
- openapiCfg := &openapinlmflocationclient.Configuration{
+ openapiCfg := &nlmfocation.Configuration{
Host: cfg.Host,
Scheme: cfg.Scheme,
DefaultHeader: cfg.DefaultHeader,
UserAgent: cfg.UserAgent,
Debug: cfg.Debug,
- Servers: []openapinlmflocationclient.ServerConfiguration{},
- OperationServers: make(map[string]openapinlmflocationclient.ServerConfigurations),
+ Servers: []nlmfocation.ServerConfiguration{},
+ OperationServers: make(map[string]nlmfocation.ServerConfigurations),
HTTPClient: cfg.HTTPClient,
}
for _, server := range cfg.Servers {
- openapiServer := openapinlmflocationclient.ServerConfiguration{
+ openapiServer := nlmfocation.ServerConfiguration{
URL: server.URL,
Description: server.Description,
- Variables: make(map[string]openapinlmflocationclient.ServerVariable),
+ Variables: make(map[string]nlmfocation.ServerVariable),
}
for name, variable := range server.Variables {
- openapiServer.Variables[name] = openapinlmflocationclient.ServerVariable{
+ openapiServer.Variables[name] = nlmfocation.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
@@ -128,15 +162,15 @@ func NewLocationClient(cfg fivegc.ClientConfiguration) *LocationClient {
openapiCfg.Servers = append(openapiCfg.Servers, openapiServer)
}
for name, servers := range cfg.OperationServers {
- openapiServers := make(openapinlmflocationclient.ServerConfigurations, len(servers))
+ openapiServers := make(nlmfocation.ServerConfigurations, len(servers))
for i, server := range servers {
- openapiServers[i] = openapinlmflocationclient.ServerConfiguration{
+ openapiServers[i] = nlmfocation.ServerConfiguration{
URL: server.URL,
Description: server.Description,
- Variables: make(map[string]openapinlmflocationclient.ServerVariable),
+ Variables: make(map[string]nlmfocation.ServerVariable),
}
for name, variable := range server.Variables {
- openapiServers[i].Variables[name] = openapinlmflocationclient.ServerVariable{
+ openapiServers[i].Variables[name] = nlmfocation.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
@@ -146,36 +180,36 @@ func NewLocationClient(cfg fivegc.ClientConfiguration) *LocationClient {
openapiCfg.OperationServers[name] = openapiServers
}
return &LocationClient{
- client: openapinlmflocationclient.NewAPIClient(openapiCfg),
+ client: nlmfocation.NewAPIClient(openapiCfg),
}
}
// LocationContextTransfer returns location context transfer request
-func (l LocationClient) LocationContextTransfer(ctx context.Context) openapinlmflocationclient.ApiLocationContextTransferRequest {
+func (l LocationClient) LocationContextTransfer(ctx context.Context) nlmfocation.ApiLocationContextTransferRequest {
return l.client.LocationContextTransferApi.LocationContextTransfer(ctx)
}
// LocationContextTransferExecute executes the location context transfer request
-func (l LocationClient) LocationContextTransferExecute(r openapinlmflocationclient.ApiLocationContextTransferRequest) (*http.Response, error) {
+func (l LocationClient) LocationContextTransferExecute(r nlmfocation.ApiLocationContextTransferRequest) (*http.Response, error) {
return r.Execute()
}
// DetermineLocation returns determine location request
-func (l LocationClient) DetermineLocation(ctx context.Context) openapinlmflocationclient.ApiDetermineLocationRequest {
+func (l LocationClient) DetermineLocation(ctx context.Context) nlmfocation.ApiDetermineLocationRequest {
return l.client.DetermineLocationApi.DetermineLocation(ctx)
}
// DetermineLocationExecute executes the determine location request
-func (l LocationClient) DetermineLocationExecute(r openapinlmflocationclient.ApiDetermineLocationRequest) (*openapinlmflocationclient.LocationData, *http.Response, error) {
+func (l LocationClient) DetermineLocationExecute(r nlmfocation.ApiDetermineLocationRequest) (*nlmfocation.LocationData, *http.Response, error) {
return r.Execute()
}
// CancelLocation returns cancel location request
-func (l LocationClient) CancelLocation(ctx context.Context) openapinlmflocationclient.ApiCancelLocationRequest {
+func (l LocationClient) CancelLocation(ctx context.Context) nlmfocation.ApiCancelLocationRequest {
return l.client.CancelLocationApi.CancelLocation(ctx)
}
// CancelLocationExecute executes the cancel location request
-func (l LocationClient) CancelLocationExecute(r openapinlmflocationclient.ApiCancelLocationRequest) (*http.Response, error) {
+func (l LocationClient) CancelLocationExecute(r nlmfocation.ApiCancelLocationRequest) (*http.Response, error) {
return r.Execute()
}
diff --git a/fivegc/nlmf/mock/broadcast.go b/fivegc/nlmf/mock/broadcast.go
index 1674573..897d4a3 100644
--- a/fivegc/nlmf/mock/broadcast.go
+++ b/fivegc/nlmf/mock/broadcast.go
@@ -1,60 +1,70 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ../broadcast.go
+
+// Package mock is a generated GoMock package.
package mock
import (
- "context"
- "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
- openapinlmfbroadcast "github.com/5GCoreNet/server-openapi/Nlmf_Broadcast"
+ context "context"
+ reflect "reflect"
+
+ fivegc "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
+ nlmf "github.com/5GCoreNet/5GCoreNetSDK/fivegc/nlmf"
+ openapi_CommonData "github.com/5GCoreNet/openapi/openapi_CommonData"
+ openapi_Nlmf_Broadcast "github.com/5GCoreNet/openapi/openapi_Nlmf_Broadcast"
+ gomock "github.com/golang/mock/gomock"
)
-// BroadcastMock is a mock of the Broadcast interface
-type BroadcastMock struct {
- cipherResponseData openapinlmfbroadcast.CipherResponseData
- problemDetails openapinlmfbroadcast.ProblemDetails
- redirectResponse fivegc.RedirectResponse
- statusCode fivegc.StatusCode
+// MockBroadcast is a mock of Broadcast interface.
+type MockBroadcast struct {
+ ctrl *gomock.Controller
+ recorder *MockBroadcastMockRecorder
}
-// NewBroadcastMock creates a new mock of the Broadcast interface
-func NewBroadcastMock(
- cipherResponseData openapinlmfbroadcast.CipherResponseData,
- problemDetails openapinlmfbroadcast.ProblemDetails,
- redirectResponse fivegc.RedirectResponse,
- statusCode fivegc.StatusCode,
-) *BroadcastMock {
- return &BroadcastMock{
- cipherResponseData: cipherResponseData,
- problemDetails: problemDetails,
- redirectResponse: redirectResponse,
- statusCode: statusCode,
- }
+// MockBroadcastMockRecorder is the mock recorder for MockBroadcast.
+type MockBroadcastMockRecorder struct {
+ mock *MockBroadcast
}
-// ProblemDetails allows to set the problem details of the mock
-func (b *BroadcastMock) ProblemDetails(problemDetails openapinlmfbroadcast.ProblemDetails) {
- b.problemDetails = problemDetails
+// NewMockBroadcast creates a new mock instance.
+func NewMockBroadcast(ctrl *gomock.Controller) *MockBroadcast {
+ mock := &MockBroadcast{ctrl: ctrl}
+ mock.recorder = &MockBroadcastMockRecorder{mock}
+ return mock
}
-// CipherResponseData allows to set the cipher response data of the mock
-func (b *BroadcastMock) CipherResponseData(cipherResponseData openapinlmfbroadcast.CipherResponseData) {
- b.cipherResponseData = cipherResponseData
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockBroadcast) EXPECT() *MockBroadcastMockRecorder {
+ return m.recorder
}
-// RedirectResponse allows to set the redirect response of the mock
-func (b *BroadcastMock) RedirectResponse(redirectResponse fivegc.RedirectResponse) {
- b.redirectResponse = redirectResponse
+// CipherKeyData mocks base method.
+func (m *MockBroadcast) CipherKeyData(arg0 context.Context, arg1 openapi_Nlmf_Broadcast.CipherRequestData) (openapi_Nlmf_Broadcast.CipherResponseData, openapi_CommonData.ProblemDetails, fivegc.RedirectResponse, nlmf.CypherResponseStatusCode) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "CipherKeyData", arg0, arg1)
+ ret0, _ := ret[0].(openapi_Nlmf_Broadcast.CipherResponseData)
+ ret1, _ := ret[1].(openapi_CommonData.ProblemDetails)
+ ret2, _ := ret[2].(fivegc.RedirectResponse)
+ ret3, _ := ret[3].(nlmf.CypherResponseStatusCode)
+ return ret0, ret1, ret2, ret3
}
-// StatusCode allows to set the status code of the mock
-func (b *BroadcastMock) StatusCode(statusCode fivegc.StatusCode) {
- b.statusCode = statusCode
+// CipherKeyData indicates an expected call of CipherKeyData.
+func (mr *MockBroadcastMockRecorder) CipherKeyData(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CipherKeyData", reflect.TypeOf((*MockBroadcast)(nil).CipherKeyData), arg0, arg1)
}
-// Error returns the problem details of the mock
-func (b *BroadcastMock) Error(ctx context.Context, err error) openapinlmfbroadcast.ProblemDetails {
- return b.problemDetails
+// Error mocks base method.
+func (m *MockBroadcast) Error(ctx context.Context, err error) openapi_CommonData.ProblemDetails {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Error", ctx, err)
+ ret0, _ := ret[0].(openapi_CommonData.ProblemDetails)
+ return ret0
}
-// CipherKeyData returns the cipher response data, the problem details, the redirect response and the status code of the mock
-func (b *BroadcastMock) CipherKeyData(ctx context.Context, data openapinlmfbroadcast.CipherRequestData) (openapinlmfbroadcast.CipherResponseData, openapinlmfbroadcast.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode) {
- return b.cipherResponseData, b.problemDetails, b.redirectResponse, b.statusCode
+// Error indicates an expected call of Error.
+func (mr *MockBroadcastMockRecorder) Error(ctx, err interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockBroadcast)(nil).Error), ctx, err)
}
diff --git a/fivegc/nlmf/mock/generate.go b/fivegc/nlmf/mock/generate.go
new file mode 100644
index 0000000..7550837
--- /dev/null
+++ b/fivegc/nlmf/mock/generate.go
@@ -0,0 +1,4 @@
+package mock
+
+//go:generate mockgen -source=../broadcast.go -destination=broadcast.go -package=mock
+//go:generate mockgen -source=../location.go -destination=location.go -package=mock
diff --git a/fivegc/nlmf/mock/location.go b/fivegc/nlmf/mock/location.go
index 39adaa6..a8b0104 100644
--- a/fivegc/nlmf/mock/location.go
+++ b/fivegc/nlmf/mock/location.go
@@ -1,70 +1,102 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ../location.go
+
+// Package mock is a generated GoMock package.
package mock
import (
- "context"
- "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
- openapinlmflocation "github.com/5GCoreNet/server-openapi/Nlmf_Location"
+ context "context"
+ reflect "reflect"
+
+ fivegc "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
+ nlmf "github.com/5GCoreNet/5GCoreNetSDK/fivegc/nlmf"
+ openapi_CommonData "github.com/5GCoreNet/openapi/openapi_CommonData"
+ openapi_Nlmf_Location "github.com/5GCoreNet/openapi/openapi_Nlmf_Location"
+ gomock "github.com/golang/mock/gomock"
)
-// LocationMock is a mock of the Location interface
-type LocationMock struct {
- locationData openapinlmflocation.LocationData
- problemDetails openapinlmflocation.ProblemDetails
- redirectResponse fivegc.RedirectResponse
- statusCode fivegc.StatusCode
+// MockLocation is a mock of Location interface.
+type MockLocation struct {
+ ctrl *gomock.Controller
+ recorder *MockLocationMockRecorder
+}
+
+// MockLocationMockRecorder is the mock recorder for MockLocation.
+type MockLocationMockRecorder struct {
+ mock *MockLocation
+}
+
+// NewMockLocation creates a new mock instance.
+func NewMockLocation(ctrl *gomock.Controller) *MockLocation {
+ mock := &MockLocation{ctrl: ctrl}
+ mock.recorder = &MockLocationMockRecorder{mock}
+ return mock
}
-// NewLocationMock creates a new mock of the Location interface
-func NewLocationMock(
- locationData openapinlmflocation.LocationData,
- problemDetails openapinlmflocation.ProblemDetails,
- redirectResponse fivegc.RedirectResponse,
- statusCode fivegc.StatusCode,
-) *LocationMock {
- return &LocationMock{
- locationData: locationData,
- problemDetails: problemDetails,
- redirectResponse: redirectResponse,
- statusCode: statusCode,
- }
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockLocation) EXPECT() *MockLocationMockRecorder {
+ return m.recorder
}
-// ProblemDetails allows to set the problem details of the mock
-func (l *LocationMock) ProblemDetails(problemDetails openapinlmflocation.ProblemDetails) {
- l.problemDetails = problemDetails
+// CancelLocation mocks base method.
+func (m *MockLocation) CancelLocation(arg0 context.Context, arg1 openapi_Nlmf_Location.CancelLocData) (openapi_CommonData.ProblemDetails, fivegc.RedirectResponse, nlmf.CancelLocationStatusCode) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "CancelLocation", arg0, arg1)
+ ret0, _ := ret[0].(openapi_CommonData.ProblemDetails)
+ ret1, _ := ret[1].(fivegc.RedirectResponse)
+ ret2, _ := ret[2].(nlmf.CancelLocationStatusCode)
+ return ret0, ret1, ret2
}
-// LocationData allows to set the location data of the mock
-func (l *LocationMock) LocationData(locationData openapinlmflocation.LocationData) {
- l.locationData = locationData
+// CancelLocation indicates an expected call of CancelLocation.
+func (mr *MockLocationMockRecorder) CancelLocation(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelLocation", reflect.TypeOf((*MockLocation)(nil).CancelLocation), arg0, arg1)
}
-// RedirectResponse allows to set the redirect response of the mock
-func (l *LocationMock) RedirectResponse(redirectResponse fivegc.RedirectResponse) {
- l.redirectResponse = redirectResponse
+// DetermineLocation mocks base method.
+func (m *MockLocation) DetermineLocation(arg0 context.Context, arg1 openapi_Nlmf_Location.InputData) (openapi_Nlmf_Location.LocationData, openapi_CommonData.ProblemDetails, fivegc.RedirectResponse, nlmf.DetermineLocationStatusCode) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DetermineLocation", arg0, arg1)
+ ret0, _ := ret[0].(openapi_Nlmf_Location.LocationData)
+ ret1, _ := ret[1].(openapi_CommonData.ProblemDetails)
+ ret2, _ := ret[2].(fivegc.RedirectResponse)
+ ret3, _ := ret[3].(nlmf.DetermineLocationStatusCode)
+ return ret0, ret1, ret2, ret3
}
-// StatusCode allows to set the status code of the mock
-func (l *LocationMock) StatusCode(statusCode fivegc.StatusCode) {
- l.statusCode = statusCode
+// DetermineLocation indicates an expected call of DetermineLocation.
+func (mr *MockLocationMockRecorder) DetermineLocation(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetermineLocation", reflect.TypeOf((*MockLocation)(nil).DetermineLocation), arg0, arg1)
}
-// Error returns the problem details of the mock
-func (l *LocationMock) Error(ctx context.Context, err error) openapinlmflocation.ProblemDetails {
- return l.problemDetails
+// Error mocks base method.
+func (m *MockLocation) Error(ctx context.Context, err error) openapi_CommonData.ProblemDetails {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Error", ctx, err)
+ ret0, _ := ret[0].(openapi_CommonData.ProblemDetails)
+ return ret0
}
-// CancelLocation returns the problem details, the redirect response and the status code of the mock
-func (l *LocationMock) CancelLocation(ctx context.Context, data openapinlmflocation.CancelLocData) (openapinlmflocation.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode) {
- return l.problemDetails, l.redirectResponse, l.statusCode
+// Error indicates an expected call of Error.
+func (mr *MockLocationMockRecorder) Error(ctx, err interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockLocation)(nil).Error), ctx, err)
}
-// DetermineLocation returns the location data, the problem details, the redirect response and the status code of the mock
-func (l *LocationMock) DetermineLocation(ctx context.Context, data openapinlmflocation.InputData) (openapinlmflocation.LocationData, openapinlmflocation.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode) {
- return l.locationData, l.problemDetails, l.redirectResponse, l.statusCode
+// LocationContextTransfer mocks base method.
+func (m *MockLocation) LocationContextTransfer(arg0 context.Context, arg1 openapi_Nlmf_Location.LocContextData) (openapi_CommonData.ProblemDetails, fivegc.RedirectResponse, nlmf.LocationContextTransferStatusCode) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "LocationContextTransfer", arg0, arg1)
+ ret0, _ := ret[0].(openapi_CommonData.ProblemDetails)
+ ret1, _ := ret[1].(fivegc.RedirectResponse)
+ ret2, _ := ret[2].(nlmf.LocationContextTransferStatusCode)
+ return ret0, ret1, ret2
}
-// LocationContextTransfer returns the problem details, the redirect response and the status code of the mock
-func (l *LocationMock) LocationContextTransfer(ctx context.Context, data openapinlmflocation.LocContextData) (openapinlmflocation.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode) {
- return l.problemDetails, l.redirectResponse, l.statusCode
+// LocationContextTransfer indicates an expected call of LocationContextTransfer.
+func (mr *MockLocationMockRecorder) LocationContextTransfer(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocationContextTransfer", reflect.TypeOf((*MockLocation)(nil).LocationContextTransfer), arg0, arg1)
}
diff --git a/fivegc/nlmf/nlmf.go b/fivegc/nlmf/server.go
similarity index 73%
rename from fivegc/nlmf/nlmf.go
rename to fivegc/nlmf/server.go
index 4d30e37..8efc843 100644
--- a/fivegc/nlmf/nlmf.go
+++ b/fivegc/nlmf/server.go
@@ -1,15 +1,13 @@
package nlmf
import (
- "fmt"
"github.com/gin-gonic/gin"
"log"
)
// Server represents a NLMF server.
type Server struct {
- ip string
- port string
+ address string // IP:PORT
apiRoot string
location Location
broadcast Broadcast
@@ -19,22 +17,22 @@ type Server struct {
}
// NewServer creates a new Server NLMF server instance.
-func NewServer(ip string, port string, apiRoot string, logger *log.Logger) *Server {
+// The address is the IP:PORT of the NLMF server.
+func NewServer(address string, apiRoot string, logger *log.Logger) *Server {
return &Server{
- ip: ip,
- port: port,
+ address: address,
apiRoot: apiRoot,
logger: logger,
stop: make(chan bool),
}
}
-// AttachLocation attaches a Location client to the NLMF Server.
+// AttachLocation attaches a Location handler to the NLMF Server.
func (n *Server) AttachLocation(l Location) {
n.location = l
}
-// AttachBroadcast attaches a Broadcast client to the NLMF Server.
+// AttachBroadcast attaches a Broadcast handler to the NLMF Server.
func (n *Server) AttachBroadcast(b Broadcast) {
n.broadcast = b
}
@@ -51,7 +49,7 @@ func (n *Server) Start() {
if n.broadcast != nil {
attachBroadcastHandler(root, n.broadcast)
}
- go n.router.Run(fmt.Sprintf("%s:%s", n.ip, n.port))
+ go n.router.Run(n.address)
<-n.stop
return
}
diff --git a/fivegc/redirect.go b/fivegc/redirect.go
index c1cb29e..f779734 100644
--- a/fivegc/redirect.go
+++ b/fivegc/redirect.go
@@ -12,9 +12,9 @@ type RedirectResponse struct {
Cause string `json:"cause,omitempty"`
- // String providing an URI formatted according to RFC 3986.
+ // String providing a URI formatted according to RFC 3986.
TargetScp string `json:"targetScp,omitempty"`
- // String providing an URI formatted according to RFC 3986.
+ // String providing a URI formatted according to RFC 3986.
TargetSepp string `json:"targetSepp,omitempty"`
}
diff --git a/fivegc/server.go b/fivegc/server.go
new file mode 100644
index 0000000..73bcf68
--- /dev/null
+++ b/fivegc/server.go
@@ -0,0 +1,11 @@
+package fivegc
+
+import (
+ "context"
+ openapicommon "github.com/5GCoreNet/openapi/openapi_CommonData"
+)
+
+type CommonInterface interface {
+ // Error returns a problem details, it is used to handle errors when unmarshalling the request.
+ Error(ctx context.Context, err error) openapicommon.ProblemDetails
+}
diff --git a/fivegc/status.go b/fivegc/status.go
index 706e796..419afa5 100644
--- a/fivegc/status.go
+++ b/fivegc/status.go
@@ -1,5 +1,7 @@
package fivegc
+// Note that this file is a port of the file status.go from Go standard library.
+
// StatusCode represents the status code of the HTTP response.
type StatusCode uint16
diff --git a/go.mod b/go.mod
index 9bcd103..1a55bd3 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
module github.com/5GCoreNet/5GCoreNetSDK
-go 1.18
+go 1.20
require (
- github.com/5GCoreNet/client-openapi v0.0.0-20230128134546-a505b74025b3
- github.com/5GCoreNet/server-openapi v0.0.0-20230126185629-9202d02e7eea
+ github.com/5GCoreNet/openapi v1.18.2
github.com/gin-gonic/gin v1.8.2
+ github.com/golang/mock v1.6.0
)
require (
@@ -23,10 +23,10 @@ require (
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
- golang.org/x/net v0.5.0 // indirect
- golang.org/x/oauth2 v0.4.0 // indirect
- golang.org/x/sys v0.4.0 // indirect
- golang.org/x/text v0.6.0 // indirect
+ golang.org/x/net v0.9.0 // indirect
+ golang.org/x/oauth2 v0.7.0 // indirect
+ golang.org/x/sys v0.7.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..584c2f5
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,128 @@
+github.com/5GCoreNet/openapi v1.18.2 h1:4HRDOTapVY+Xr49KmiS7R4TAuwMEpNwg6Z+oiXM0mnY=
+github.com/5GCoreNet/openapi v1.18.2/go.mod h1:10RqDFgIY+AgfRk626E0+3e9NbooVSvE/SsZs4mQa1w=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
+github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
+github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
+github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
+github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
+github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
+github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
+github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/header/header_test.go b/internal/header/header_test.go
new file mode 100644
index 0000000..b07bbd9
--- /dev/null
+++ b/internal/header/header_test.go
@@ -0,0 +1,24 @@
+package header
+
+import (
+ "github.com/5GCoreNet/5GCoreNetSDK/fivegc"
+ "github.com/gin-gonic/gin"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestBindRedirectHeader(t *testing.T) {
+ ginContext, _ := gin.CreateTestContext(&httptest.ResponseRecorder{})
+ BindRedirectHeader(ginContext, fivegc.RedirectHeader{
+ Location: "http://localhost:8080",
+ SbiTarget: "1234",
+ })
+
+ if ginContext.Writer.Header().Get("Location") != "http://localhost:8080" {
+ t.Errorf("Location header not set")
+ }
+
+ if ginContext.Writer.Header().Get("3gpp-Sbi-Target-Nf-Id") != "1234" {
+ t.Errorf("3gpp-Sbi-Target-Nf-Id header not set")
+ }
+}