From d2f1f7d4bf4ce960ccedb781f976dea2d4a28f96 Mon Sep 17 00:00:00 2001 From: Fabian <-> Date: Fri, 27 Mar 2020 23:18:52 +0100 Subject: [PATCH] added a example for basic ipp options and comments for the attribute.go file --- README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++--- attribute.go | 13 +++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1106328..b18cc20 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Version](https://img.shields.io/github/release-pre/phin1x/go-ipp.svg)](https://github.com/phin1x/go-ipp/releases/tag/v1.4.1) [![Documentation](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/phin1x/go-ipp?tab=doc) +[![Go Report Card](https://goreportcard.com/badge/github.com/phin1x/go-ipp)](https://goreportcard.com/report/github.com/phin1x/go-ipp) [![Licence](https://img.shields.io/github/license/phin1x/go-ipp.svg)](https://github.com/phin1x/go-ipp/blob/master/LICENSE) ## Go Get @@ -18,12 +19,85 @@ go get -u github.com/phin1x/go-ipp * create custom ipp requests * parse ipp responses and ipp control files -## Examples +## Example -Print a file +Print a file with the ipp client ```go -client := ipp.NewIPPClient("printserver", 631, "user", "password", true) -client.PrintFile("/path/to/file", "my-printer", map[string]interface{}{}) +package main + +import "github.com/phin1x/go-ipp" + +func main() { + // create a new ipp client + client := ipp.NewIPPClient("printserver", 631, "user", "password", true) + // print file + client.PrintFile("/path/to/file", "my-printer", map[string]interface{}{}) +} +``` + +Craft and send a custom request +```go + +package main + +import "github.com/phin1x/go-ipp" + +func main() { + // define a ipp request + req := ipp.NewRequest(OperationGetJobs, 1) + req.OperationAttributes[ipp.AttributeWhichJobs] = "completed" + req.OperationAttributes[ipp.AttributeMyJobs] = myJobs + req.OperationAttributes[ipp.AttributeFirstJobID] = 42 + req.OperationAttributes[ipp.AttributeRequestingUserName] = "fabian" + + // encode request to bytes + payload, err := req.Encode() + if err != nil { + panic(err) + } + + // send ipp request to remote server via http + httpReq, err := http.NewRequest("POST", "http://my-print-server:631/printers/my-printer", bytes.NewBuffer(payload)) + if err != nil { + panic(err) + } + + // set oüü headers + httpReq.Header.Set("Content-Length", len(payload)) + httpReq.Header.Set("Content-Type", ipp.ContentTypeIPP) + + httpClient := &http.Client() + httpResp, err := httpClient.Do(httpReq) + if err != nil { + panic(err) + } + defer httpResp.Body.Close() + + // response must be 200 for a successful operation + // other possible http codes are: + // - 500 -> server error + // - 426 -> sever requests a encrypted connection + // - 401 -> forbidden -> need authorization header or user is not permitted + if httpResp.StatusCode != 200 { + panic("non 200 response from server") + } + + // decode ipp response + resp, err := ipp.NewResponseDecoder(httpResp.Body).Decode(nil) + if err != nil { + panic(err) + } + + // check if the response status is "ok" + if resp.StatusCode == ipp.StatusOk { + panic(resp.StatusCode) + } + + // do something with the returned data + for _, job := resp.JobAttributes { + // ... + } +} ``` ## Licence diff --git a/attribute.go b/attribute.go index ba77928..383a033 100644 --- a/attribute.go +++ b/attribute.go @@ -11,14 +11,19 @@ const ( sizeBoolean = int16(1) ) +// ipp attribute encoder +// encodes attribute to a io.Writer type AttributeEncoder struct { writer io.Writer } +// create a new attribute encoder from a writer func NewAttributeEncoder(w io.Writer) *AttributeEncoder { return &AttributeEncoder{w} } +// encodes a attribute and its value to a io.Writer +// the tag is determined by the AttributeTagMapping map func (e *AttributeEncoder) Encode(attribute string, value interface{}) error { tag, ok := AttributeTagMapping[attribute] if !ok { @@ -338,20 +343,27 @@ func (e *AttributeEncoder) writeNullByte() error { return binary.Write(e.writer, binary.BigEndian, int16(0)) } +// representation of a ipp attribute +// a attribute contains a tag, witch identifies the type, the name of the attribute a the value type Attribute struct { Tag int8 Name string Value interface{} } +// ipp attribute decoder +// reads from a io.Reader an decode the data into an attribute struct type AttributeDecoder struct { reader io.Reader } +// create a new attribute decoder from a reader func NewAttributeDecoder(r io.Reader) *AttributeDecoder { return &AttributeDecoder{r} } +// reads from a io.Reader and decode the attribute +// the type is identified by a tag passed as an argument func (d *AttributeDecoder) Decode(tag int8) (*Attribute, error) { attr := Attribute{Tag: tag} @@ -486,6 +498,7 @@ func (d *AttributeDecoder) decodeRange() ([]int, error) { return r, nil } +// represents the data of the resolution attribute type Resolution struct { Height int Width int